home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / server.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  109KB  |  4,177 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Main SMB server routines
  5.    Copyright (C) Andrew Tridgell 1992-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "includes.h"
  23. #include "loadparm.h"
  24. #include "pcap.h"
  25. #include "trans2.h"
  26. #include "reply.h"
  27.  
  28. pstring servicesf = CONFIGFILE;
  29. pstring OriginalDir ="/";
  30. extern pstring debugf;
  31. extern pstring sesssetup_user;
  32.  
  33. char *InBuffer = NULL;
  34. char *OutBuffer = NULL;
  35. char *last_inbuf = NULL;
  36.  
  37. int initial_uid = 0;
  38. int initial_gid = 0;
  39.  
  40. BOOL share_mode_pending = False;
  41.  
  42. /* have I done a become_user? */
  43. static struct {
  44.   int cnum, uid;
  45. } last_user;
  46.  
  47. /* the last message the was processed */
  48. int last_message = -1;
  49.  
  50. /* a useful macro to debug the last message processed */
  51. #define LAST_MESSAGE() smb_fn_name(last_message)
  52.  
  53. extern pstring scope;
  54. extern int DEBUGLEVEL;
  55. extern int case_default;
  56. extern BOOL case_sensitive;
  57. extern BOOL case_preserve;
  58. extern BOOL use_mangled_map;
  59. extern BOOL short_case_preserve;
  60. extern BOOL case_mangle;
  61. extern time_t smb_last_time;
  62.  
  63. extern pstring user_socket_options;
  64.  
  65. connection_struct Connections[MAX_CONNECTIONS];
  66. files_struct Files[MAX_OPEN_FILES];
  67.  
  68. extern int Protocol;
  69.  
  70. int maxxmit = BUFFER_SIZE;
  71.  
  72. int chain_size = 0;
  73.  
  74. /* a fnum to use when chaining */
  75. int chain_fnum = -1;
  76.  
  77. /* number of open connections */
  78. static int num_connections_open = 0;
  79.  
  80. extern fstring remote_machine;
  81.  
  82.  
  83. /* these can be set by some functions to override the error codes */
  84. int unix_ERR_class=SUCCESS;
  85. int unix_ERR_code=0;
  86.  
  87.  
  88. extern int extra_time_offset;
  89.  
  90. extern pstring myhostname;
  91. extern struct in_addr myip;
  92.  
  93.  
  94. static int find_free_connection(int hash);
  95.  
  96. #ifdef SMB_PASSWD
  97. extern void generate_next_challenge(char *challenge);
  98. extern void set_challenge(char *challenge);
  99. #endif
  100.  
  101. /* for readability... */
  102. #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
  103. #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
  104. #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
  105. #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
  106. #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
  107.  
  108.  
  109.  
  110. /****************************************************************************
  111.   change a dos mode to a unix mode
  112.     base permission for files:
  113.          everybody gets read bit set
  114.          dos readonly is represented in unix by removing everyone's write bit
  115.          dos archive is represented in unix by the user's execute bit
  116.          dos system is represented in unix by the group's execute bit
  117.          dos hidden is represented in unix by the other's execute bit
  118.     base permission for directories:
  119.          dos directory is represented in unix by unix's dir bit and the exec bit
  120. ****************************************************************************/
  121. mode_t unix_mode(int cnum,int dosmode)
  122. {
  123.   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
  124.  
  125.   if ( !IS_DOS_READONLY(dosmode) )
  126.     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
  127.  
  128.   if (IS_DOS_DIR(dosmode))
  129.     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
  130.  
  131.   if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
  132.     result |= S_IXUSR;
  133.  
  134.   if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
  135.     result |= S_IXGRP;
  136.  
  137.   if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
  138.     result |= S_IXOTH;  
  139.  
  140.   result &= CREATE_MODE(cnum);
  141.   return(result);
  142. }
  143.  
  144.  
  145. /****************************************************************************
  146.   change a unix mode to a dos mode
  147. ****************************************************************************/
  148. int dos_mode(int cnum,char *path,struct stat *sbuf)
  149. {
  150.   int result = 0;
  151.  
  152. #if OLD_DOS_MODE
  153.   if (!CAN_WRITE(cnum) || !((sbuf->st_mode & S_IWOTH) ||
  154.                 Connections[cnum].admin_user ||
  155.                 ((sbuf->st_mode & S_IWUSR) && 
  156.                  Connections[cnum].uid==sbuf->st_uid) ||
  157.                 ((sbuf->st_mode & S_IWGRP) && 
  158.                  in_group(sbuf->st_gid,Connections[cnum].gid,
  159.                       Connections[cnum].ngroups,
  160.                       Connections[cnum].igroups))))
  161.     result |= aRONLY;
  162. #else
  163.   if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
  164.     if (!((sbuf->st_mode & S_IWOTH) ||
  165.       Connections[cnum].admin_user ||
  166.       ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid==sbuf->st_uid) ||
  167.       ((sbuf->st_mode & S_IWGRP) && 
  168.        in_group(sbuf->st_gid,Connections[cnum].gid,
  169.             Connections[cnum].ngroups,Connections[cnum].igroups))))
  170.       result |= aRONLY;
  171.   } else {
  172.     if ((sbuf->st_mode & S_IWUSR) == 0)
  173.       result |= aRONLY;
  174.   }
  175. #endif
  176.  
  177.   if ((sbuf->st_mode & S_IXUSR) != 0)
  178.     result |= aARCH;
  179.  
  180.   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
  181.     result |= aSYSTEM;
  182.  
  183.   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
  184.     result |= aHIDDEN;   
  185.   
  186.   if (S_ISDIR(sbuf->st_mode))
  187.     result = aDIR | (result & aRONLY);
  188.  
  189. #if LINKS_READ_ONLY
  190.   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
  191.     result |= aRONLY;
  192. #endif
  193.  
  194.   /* hide files with a name starting with a . */
  195.   if (lp_hide_dot_files(SNUM(cnum)))
  196.     {
  197.       char *p = strrchr(path,'/');
  198.       if (p)
  199.     p++;
  200.       else
  201.     p = path;
  202.       
  203.       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
  204.     result |= aHIDDEN;
  205.     }
  206.  
  207.   return(result);
  208. }
  209.  
  210.  
  211. /*******************************************************************
  212. chmod a file - but preserve some bits
  213. ********************************************************************/
  214. int dos_chmod(int cnum,char *fname,int dosmode)
  215. {
  216.   struct stat st;
  217.   int mask=0;
  218.   int tmp;
  219.   int unixmode;
  220.  
  221.   if (sys_stat(fname,&st)) return(-1);
  222.  
  223.   if (S_ISDIR(st.st_mode)) dosmode |= aDIR;
  224.  
  225.   if (dos_mode(cnum,fname,&st) == dosmode) return(0);
  226.  
  227.   unixmode = unix_mode(cnum,dosmode);
  228.  
  229.   /* preserve the s bits */
  230.   mask |= (S_ISUID | S_ISGID);
  231.  
  232.   /* preserve the t bit */
  233. #ifdef S_ISVTX
  234.   mask |= S_ISVTX;
  235. #endif
  236.  
  237.   /* possibly preserve the x bits */
  238.   if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
  239.   if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
  240.   if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
  241.  
  242.   unixmode |= (st.st_mode & mask);
  243.  
  244.   /* if we previously had any r bits set then leave them alone */
  245.   if ((tmp = st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
  246.     unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
  247.     unixmode |= tmp;
  248.   }
  249.  
  250.   /* if we previously had any w bits set then leave them alone 
  251.    if the new mode is not rdonly */
  252.   if (!IS_DOS_READONLY(dosmode) &&
  253.       (tmp = st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
  254.     unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
  255.     unixmode |= tmp;
  256.   }
  257.     
  258.   return(chmod(fname,unixmode));
  259. }
  260.  
  261.  
  262. /****************************************************************************
  263. check if two filenames are equal
  264.  
  265. this needs to be careful about whether we are case sensitive
  266. ****************************************************************************/
  267. static BOOL fname_equal(char *name1, char *name2)
  268. {
  269.   int l1 = strlen(name1);
  270.   int l2 = strlen(name2);
  271.  
  272.   /* handle filenames ending in a single dot */
  273.   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
  274.     {
  275.       BOOL ret;
  276.       name1[l1-1] = 0;
  277.       ret = fname_equal(name1,name2);
  278.       name1[l1-1] = '.';
  279.       return(ret);
  280.     }
  281.  
  282.   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
  283.     {
  284.       BOOL ret;
  285.       name2[l2-1] = 0;
  286.       ret = fname_equal(name1,name2);
  287.       name2[l2-1] = '.';
  288.       return(ret);
  289.     }
  290.  
  291.   /* now normal filename handling */
  292.   if (case_sensitive)
  293.     return(strcmp(name1,name2) == 0);
  294.  
  295.   return(strequal(name1,name2));
  296. }
  297.  
  298.  
  299. /****************************************************************************
  300. mangle the 2nd name and check if it is then equal to the first name
  301. ****************************************************************************/
  302. static BOOL mangled_equal(char *name1, char *name2)
  303. {
  304.   pstring tmpname;
  305.  
  306.   if (is_8_3(name2))
  307.     return(False);
  308.  
  309.   strcpy(tmpname,name2);
  310.   mangle_name_83(tmpname);
  311.  
  312.   return(strequal(name1,tmpname));
  313. }
  314.  
  315.  
  316. /****************************************************************************
  317. scan a directory to find a filename, matching without case sensitivity
  318.  
  319. If the name looks like a mangled name then try via the mangling functions
  320. ****************************************************************************/
  321. static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
  322. {
  323.   void *cur_dir;
  324.   char *dname;
  325.   BOOL mangled;
  326.   fstring name2;
  327.  
  328.   mangled = is_mangled(name);
  329.  
  330.   /* handle null paths */
  331.   if (*path == 0)
  332.     path = ".";
  333.  
  334.   if (docache && (dname = DirCacheCheck(path,name,snum))) {
  335.     strcpy(name, dname);    
  336.     return(True);
  337.   }      
  338.  
  339.   if (mangled)
  340.     check_mangled_stack(name);
  341.  
  342.   /* open the directory */
  343.   if (!(cur_dir = OpenDir(path))) 
  344.     {
  345.       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
  346.       return(False);
  347.     }
  348.  
  349.   /* now scan for matching names */
  350.   while ((dname = ReadDirName(cur_dir))) 
  351.     {
  352.       if (*dname == '.' &&
  353.       (strequal(dname,".") || strequal(dname,"..")))
  354.     continue;
  355.  
  356.       strcpy(name2,dname);
  357.       if (!name_map_mangle(name2,False,snum)) continue;
  358.  
  359.       if ((mangled && mangled_equal(name,name2))
  360.       || fname_equal(name, name2))
  361.     {
  362.       /* we've found the file, change it's name and return */
  363.       if (docache) DirCacheAdd(path,name,dname,snum);
  364.       strcpy(name, dname);
  365.       CloseDir(cur_dir);
  366.       return(True);
  367.     }
  368.     }
  369.  
  370.   CloseDir(cur_dir);
  371.   return(False);
  372. }
  373.  
  374. /****************************************************************************
  375. This routine is called to convert names from the dos namespace to unix
  376. namespace. It needs to handle any case conversions, mangling, format
  377. changes etc.
  378.  
  379. We assume that we have already done a chdir() to the right "root" directory
  380. for this service.
  381.  
  382. The function will return False if some part of the name except for the last
  383. part cannot be resolved
  384. ****************************************************************************/
  385. BOOL unix_convert(char *name,int cnum)
  386. {
  387.   struct stat st;
  388.   char *start, *end;
  389.   pstring dirpath;
  390.  
  391.   *dirpath = 0;
  392.  
  393.   /* convert to basic unix format - removing \ chars and cleaning it up */
  394.   unix_format(name);
  395.   unix_clean_name(name);
  396.  
  397.   if (!case_sensitive && 
  398.       (!case_preserve || (is_8_3(name) && !short_case_preserve)))
  399.     strnorm(name);
  400.  
  401.   /* names must be relative to the root of the service - trim any leading /.
  402.    also trim trailing /'s */
  403.   trim_string(name,"/","/");
  404.  
  405.   /* check if it's a printer file */
  406.   if (Connections[cnum].printer)
  407.     {
  408.       if ((! *name) || strchr(name,'/') || !is_8_3(name))
  409.     {
  410.       fstring name2;
  411.       sprintf(name2,"%.6s.XXXXXX",remote_machine);
  412.       strcpy(name,(char *)mktemp(name2));      
  413.     }      
  414.       return(True);
  415.     }
  416.  
  417.   /* stat the name - if it exists then we are all done! */
  418.   if (sys_stat(name,&st) == 0)
  419.     return(True);
  420.  
  421.   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
  422.  
  423.   /* a special case - if we don't have any mangling chars and are case
  424.      sensitive then searching won't help */
  425.   if (case_sensitive && !is_mangled(name) && 
  426.       !lp_strip_dot() && !use_mangled_map)
  427.     return(False);
  428.  
  429.   /* now we need to recursively match the name against the real 
  430.      directory structure */
  431.  
  432.   start = name;
  433.   while (strncmp(start,"./",2) == 0)
  434.     start += 2;
  435.  
  436.   /* now match each part of the path name separately, trying the names
  437.      as is first, then trying to scan the directory for matching names */
  438.   for (;start;start = (end?end+1:(char *)NULL)) 
  439.     {
  440.       /* pinpoint the end of this section of the filename */
  441.       end = strchr(start, '/');
  442.  
  443.       /* chop the name at this point */
  444.       if (end) *end = 0;
  445.  
  446.       /* check if the name exists up to this point */
  447.       if (sys_stat(name, &st) == 0) 
  448.     {
  449.       /* it exists. it must either be a directory or this must be
  450.          the last part of the path for it to be OK */
  451.       if (end && !(st.st_mode & S_IFDIR)) 
  452.         {
  453.           /* an intermediate part of the name isn't a directory */
  454.           DEBUG(5,("Not a dir %s\n",start));
  455.           *end = '/';
  456.           return(False);
  457.         }
  458.     }
  459.       else 
  460.     {
  461.       pstring rest;
  462.  
  463.       *rest = 0;
  464.  
  465.       /* remember the rest of the pathname so it can be restored
  466.          later */
  467.       if (end) strcpy(rest,end+1);
  468.  
  469.  
  470.       /* try to find this part of the path in the directory */
  471.       if (strchr(start,'?') || strchr(start,'*') ||
  472.           !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
  473.         {
  474.           if (end) 
  475.         {
  476.           /* an intermediate part of the name can't be found */
  477.           DEBUG(5,("Intermediate not found %s\n",start));
  478.           *end = '/';
  479.           return(False);
  480.         }
  481.           
  482.           /* just the last part of the name doesn't exist */
  483.           /* we may need to strupper() or strlower() it in case
  484.          this conversion is being used for file creation 
  485.          purposes */
  486.           /* if the filename is of mixed case then don't normalise it */
  487.           if (!case_preserve && 
  488.           (!strhasupper(start) || !strhaslower(start)))        
  489.         strnorm(start);
  490.  
  491.           /* check on the mangled stack to see if we can recover the 
  492.          base of the filename */
  493.           if (is_mangled(start))
  494.         check_mangled_stack(start);
  495.  
  496.           DEBUG(5,("New file %s\n",start));
  497.           return(True); 
  498.         }
  499.  
  500.       /* restore the rest of the string */
  501.       if (end) 
  502.         {
  503.           strcpy(start+strlen(start)+1,rest);
  504.           end = start + strlen(start);
  505.         }
  506.     }
  507.  
  508.       /* add to the dirpath that we have resolved so far */
  509.       if (*dirpath) strcat(dirpath,"/");
  510.       strcat(dirpath,start);
  511.  
  512.       /* restore the / that we wiped out earlier */
  513.       if (end) *end = '/';
  514.     }
  515.   
  516.   /* the name has been resolved */
  517.   DEBUG(5,("conversion finished %s\n",name));
  518.   return(True);
  519. }
  520.  
  521.  
  522.  
  523.  
  524. #ifdef QUOTAS
  525. #ifndef CRAY
  526. /****************************************************************************
  527. try to get the disk space from disk quotas
  528. ****************************************************************************/
  529. static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  530. {
  531.   uid_t user_id, euser_id;
  532.   int r;
  533.   char dev_disk[256];
  534.   struct dqblk D;
  535.   struct stat S;
  536.   /* find the block device file */
  537.   if ((stat(path, &S)<0) ||
  538.       (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
  539.  
  540.   euser_id = geteuid();
  541.  
  542. #ifdef USE_SETRES
  543.   /* for HPUX, real uid must be same as euid to execute quotactl for euid */
  544.   user_id = getuid();
  545.   setresuid(euser_id,-1,-1);
  546. #endif
  547.   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
  548.   #ifdef USE_SETRES
  549.   if (setresuid(user_id,-1,-1))
  550.     DEBUG(5,("Unable to reset uid to %d\n", user_id));
  551.   #endif
  552.   /* Use softlimit to determine disk space, except when it has been exceeded */
  553.   *bsize = 1024;
  554.   if (r)
  555.     {
  556.       if (errno == EDQUOT) 
  557.     {
  558.        *dfree =0;
  559.        *dsize =D.dqb_curblocks;
  560.        return (True);
  561.     }
  562.       else return(False);
  563.     }
  564.   /* Use softlimit to determine disk space, except when it has been exceeded */
  565.   if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curfiles>D.dqb_fsoftlimit)) 
  566.     {
  567.       *dfree = 0;
  568.       *dsize = D.dqb_curblocks;
  569.     }
  570.   else {
  571.     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
  572.     *dsize = D.dqb_bsoftlimit;
  573.   }
  574.   return (True);
  575. }
  576. #else
  577. /****************************************************************************
  578. try to get the disk space from disk quotas (CRAY VERSION)
  579. ****************************************************************************/
  580. static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
  581. {
  582.   struct mntent *mnt;
  583.   FILE *fd;
  584.   struct stat sbuf;
  585.   dev_t devno ;
  586.   static dev_t devno_cached = 0 ;
  587.   static char name[MNTMAXSTR] ;
  588.   struct q_request request ;
  589.   struct qf_header header ;
  590.   static int quota_default = 0 ;
  591.   int found ;
  592.   
  593.   if ( stat(path,&sbuf) == -1 )
  594.     return(False) ;
  595.   
  596.   devno = sbuf.st_dev ;
  597.   
  598.   if ( devno != devno_cached ) {
  599.     
  600.     devno_cached = devno ;
  601.     
  602.     if ((fd = setmntent(KMTAB)) == NULL)
  603.       return(False) ;
  604.     
  605.     found = False ;
  606.     
  607.     while ((mnt = getmntent(fd)) != NULL) {
  608.       
  609.       if ( stat(mnt->mnt_dir,&sbuf) == -1 )
  610.     continue ;
  611.       
  612.       if (sbuf.st_dev == devno) {
  613.     
  614.     found = True ;
  615.     break ;
  616.     
  617.       }
  618.       
  619.     }
  620.     
  621.     strcpy(name,mnt->mnt_dir) ;
  622.     endmntent(fd) ;
  623.     
  624.     if ( ! found )
  625.       return(False) ;
  626.   }
  627.   
  628.   request.qf_magic = QF_MAGIC ;
  629.   request.qf_entry.id = geteuid() ;
  630.   
  631.   if (quotactl(name, Q_GETQUOTA, &request) == -1)
  632.     return(False) ;
  633.   
  634.   if ( ! request.user )
  635.     return(False) ;
  636.   
  637.   if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
  638.     
  639.     if ( ! quota_default ) {
  640.       
  641.       if ( quotactl(name, Q_GETHEADER, &header) == -1 )
  642.     return(False) ;
  643.       else
  644.     quota_default = header.user_h.def_fq ;
  645.     }
  646.     
  647.     *dfree = quota_default ;
  648.     
  649.   }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
  650.     
  651.     *dfree = 0 ;
  652.     
  653.   }else{
  654.     
  655.     *dfree = request.qf_entry.user_q.f_quota ;
  656.     
  657.   }
  658.   
  659.   *dsize = request.qf_entry.user_q.f_use ;
  660.   
  661.   if ( *dfree )
  662.     *dfree -= *dsize ;
  663.   
  664.   if ( *dfree < 0 )
  665.     *dfree = 0 ;
  666.   
  667.   *bsize = 4096 ;  /* Cray blocksize */
  668.   
  669.   return(True) ;
  670.   
  671. }
  672. #endif /* CRAY */
  673. #endif /* QUOTAS */
  674.  
  675.  
  676. /****************************************************************************
  677. normalise for DOS usage 
  678. ****************************************************************************/
  679. static void disk_norm(int *bsize,int *dfree,int *dsize)
  680. {
  681.   /* check if the disk is beyond the max disk size */
  682.   int maxdisksize = lp_maxdisksize();
  683.   if (maxdisksize) {
  684.     /* convert to blocks - and don't overflow */
  685.     maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
  686.     if (*dsize > maxdisksize) *dsize = maxdisksize;
  687.     if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop 
  688.                              applications getting 
  689.                              div by 0 errors */
  690.   }  
  691.  
  692.   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
  693.     {
  694.       *dfree /= 2;
  695.       *dsize /= 2;
  696.       *bsize *= 2;
  697.       if (*bsize > WORDMAX )
  698.     {
  699.       *bsize = WORDMAX;
  700.       if (*dsize > WORDMAX)
  701.         *dsize = WORDMAX;
  702.       if (*dfree >  WORDMAX)
  703.         *dfree = WORDMAX;
  704.       break;
  705.     }
  706.     }
  707. }
  708.  
  709. /****************************************************************************
  710.   return number of 1K blocks available on a path and total number 
  711. ****************************************************************************/
  712. int disk_free(char *path,int *bsize,int *dfree,int *dsize)
  713. {
  714.   char *df_command = lp_dfree_command();
  715. #ifndef NO_STATFS
  716. #ifdef USE_STATVFS
  717.   struct statvfs fs;
  718. #else
  719. #ifdef ULTRIX
  720.   struct fs_data fs;
  721. #else
  722.   struct statfs fs;
  723. #endif
  724. #endif
  725. #endif
  726.  
  727. #ifdef QUOTAS
  728.   if (disk_quotas(path, bsize, dfree, dsize))
  729.     {
  730.       disk_norm(bsize,dfree,dsize);
  731.       return(((*bsize)/1024)*(*dfree));
  732.     }
  733. #endif
  734.  
  735.  
  736.   /* possibly use system() to get the result */
  737.   if (df_command && *df_command)
  738.     {
  739.       int ret;
  740.       pstring syscmd;
  741.       pstring outfile;
  742.       
  743.       sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
  744.       sprintf(syscmd,"%s %s",df_command,path);
  745.       standard_sub_basic(syscmd);
  746.  
  747.       ret = smbrun(syscmd,outfile);
  748.       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  749.       
  750.       {
  751.     FILE *f = fopen(outfile,"r");    
  752.     *dsize = 0;
  753.     *dfree = 0;
  754.     *bsize = 1024;
  755.     if (f)
  756.       {
  757.         fscanf(f,"%d %d %d",dsize,dfree,bsize);
  758.         fclose(f);
  759.       }
  760.     else
  761.       DEBUG(0,("Can't open %s\n",outfile));
  762.       }
  763.       
  764.       unlink(outfile);
  765.       disk_norm(bsize,dfree,dsize);
  766.       return(((*bsize)/1024)*(*dfree));
  767.     }
  768.  
  769. #ifdef NO_STATFS
  770.   DEBUG(1,("Warning - no statfs function\n"));
  771.   return(1);
  772. #else
  773. #ifdef STATFS4
  774.   if (statfs(path,&fs,sizeof(fs),0) != 0)
  775. #else
  776. #ifdef USE_STATVFS
  777.     if (statvfs(path, &fs))
  778. #else
  779. #ifdef STATFS3
  780.       if (statfs(path,&fs,sizeof(fs)) == -1)     
  781. #else
  782.     if (statfs(path,&fs) == -1)
  783. #endif /* STATFS3 */
  784. #endif /* USE_STATVFS */
  785. #endif /* STATFS4 */
  786.       {
  787.         DEBUG(3,("dfree call failed code errno=%d\n",errno));
  788.         *bsize = 1024;
  789.         *dfree = 1;
  790.         *dsize = 1;
  791.         return(((*bsize)/1024)*(*dfree));
  792.       }
  793.  
  794. #ifdef ULTRIX
  795.   *bsize = 1024;
  796.   *dfree = fs.fd_req.bfree;
  797.   *dsize = fs.fd_req.btot;
  798. #else
  799. #ifdef USE_STATVFS
  800.   *bsize = fs.f_frsize;
  801. #else
  802. #ifdef USE_F_FSIZE
  803.   /* eg: osf1 has f_fsize = fundamental filesystem block size, 
  804.      f_bsize = optimal transfer block size (MX: 94-04-19) */
  805.   *bsize = fs.f_fsize;
  806. #else
  807.   *bsize = fs.f_bsize;
  808. #endif /* STATFS3 */
  809. #endif /* USE_STATVFS */
  810.  
  811. #ifdef STATFS4
  812.   *dfree = fs.f_bfree;
  813. #else
  814.   *dfree = fs.f_bavail;
  815. #endif /* STATFS4 */
  816.   *dsize = fs.f_blocks;
  817. #endif /* ULTRIX */
  818.  
  819. #if defined(SCO) || defined(ISC) || defined(MIPS)
  820.   *bsize = 512;
  821. #endif
  822.  
  823. /* handle rediculous bsize values - some OSes are broken */
  824. if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
  825.  
  826.   disk_norm(bsize,dfree,dsize);
  827.  
  828.   if (*bsize < 256)
  829.     *bsize = 512;
  830.   if ((*dsize)<1)
  831.     {
  832.       DEBUG(0,("dfree seems to be broken on your system\n"));
  833.       *dsize = 20*1024*1024/(*bsize);
  834.       *dfree = MAX(1,*dfree);
  835.     }
  836.   return(((*bsize)/1024)*(*dfree));
  837. #endif
  838. }
  839.  
  840.  
  841. /****************************************************************************
  842. wrap it to get filenames right
  843. ****************************************************************************/
  844. int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
  845. {
  846.   return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
  847. }
  848.  
  849.  
  850.  
  851. /****************************************************************************
  852. check a filename - possibly caling reducename
  853.  
  854. This is called by every routine before it allows an operation on a filename.
  855. It does any final confirmation necessary to ensure that the filename is
  856. a valid one for the user to access.
  857. ****************************************************************************/
  858. BOOL check_name(char *name,int cnum)
  859. {
  860.   BOOL ret;
  861.  
  862.   errno = 0;
  863.  
  864.   ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
  865.   if (!ret)
  866.     DEBUG(5,("check_name on %s failed\n",name));
  867.  
  868.   return(ret);
  869. }
  870.  
  871. /****************************************************************************
  872. check a filename - possibly caling reducename
  873. ****************************************************************************/
  874. static void check_for_pipe(char *fname)
  875. {
  876.   /* special case of pipe opens */
  877.   char s[10];
  878.   StrnCpy(s,fname,9);
  879.   strlower(s);
  880.   if (strstr(s,"pipe/"))
  881.     {
  882.       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
  883.       unix_ERR_class = ERRSRV;
  884.       unix_ERR_code = ERRaccess;
  885.     }
  886. }
  887.  
  888.  
  889. /****************************************************************************
  890. open a file
  891. ****************************************************************************/
  892. void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
  893. {
  894.   pstring fname;
  895.  
  896.   Files[fnum].open = False;
  897.   Files[fnum].fd = -1;
  898.   errno = EPERM;
  899.  
  900.   strcpy(fname,fname1);
  901.  
  902.   /* check permissions */
  903.   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
  904.     {
  905.       DEBUG(3,("Permission denied opening %s\n",fname));
  906.       check_for_pipe(fname);
  907.       return;
  908.     }
  909.  
  910.   /* this handles a bug in Win95 - it doesn't say to create the file when it 
  911.      should */
  912.   if (Connections[cnum].printer)
  913.     flags |= O_CREAT;
  914.  
  915. /*
  916.   if (flags == O_WRONLY)
  917.     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
  918. */
  919.  
  920. #if UTIME_WORKAROUND
  921.   /* XXXX - is this OK?? */
  922.   /* this works around a utime bug but can cause other problems */
  923.   if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
  924.     sys_unlink(fname);
  925. #endif
  926.  
  927.  
  928.   Files[fnum].fd = sys_open(fname,flags,mode);
  929.  
  930.   if ((Files[fnum].fd>=0) && 
  931.       Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
  932.     pstring dname;
  933.     int dum1,dum2,dum3;
  934.     char *p;
  935.     strcpy(dname,fname);
  936.     p = strrchr(dname,'/');
  937.     if (p) *p = 0;
  938.     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
  939.     lp_minprintspace(SNUM(cnum))) {
  940.       close(Files[fnum].fd);
  941.       Files[fnum].fd = -1;
  942.       sys_unlink(fname);
  943.       errno = ENOSPC;
  944.       return;
  945.     }
  946.   }
  947.     
  948.  
  949.   /* Fix for files ending in '.' */
  950.   if((Files[fnum].fd == -1) && (errno == ENOENT) && 
  951.      (strchr(fname,'.')==NULL))
  952.     {
  953.       strcat(fname,".");
  954.       Files[fnum].fd = sys_open(fname,flags,mode);
  955.     }
  956.  
  957. #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
  958.   if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
  959.     {
  960.       int max_len;
  961.       char *p = strrchr(fname, '/');
  962.  
  963.       if (p == fname)    /* name is "/xxx" */
  964.     {
  965.       max_len = pathconf("/", _PC_NAME_MAX);
  966.       p++;
  967.     }
  968.       else if ((p == NULL) || (p == fname))
  969.     {
  970.       p = fname;
  971.       max_len = pathconf(".", _PC_NAME_MAX);
  972.     }
  973.       else
  974.     {
  975.       *p = '\0';
  976.       max_len = pathconf(fname, _PC_NAME_MAX);
  977.       *p = '/';
  978.       p++;
  979.     }
  980.       if (strlen(p) > max_len)
  981.     {
  982.       char tmp = p[max_len];
  983.  
  984.       p[max_len] = '\0';
  985.       if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
  986.         p[max_len] = tmp;
  987.     }
  988.     }
  989. #endif
  990.  
  991.   if (Files[fnum].fd < 0)
  992.     {
  993.       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
  994.            fname,strerror(errno),flags));
  995.       check_for_pipe(fname);
  996.       return;
  997.     }
  998.  
  999.   if (Files[fnum].fd >= 0)
  1000.     {
  1001.       struct stat st;
  1002.       Connections[cnum].num_files_open++;
  1003.       fstat(Files[fnum].fd,&st);
  1004.       Files[fnum].mode = st.st_mode;
  1005.       Files[fnum].open_time = time(NULL);
  1006.       Files[fnum].size = 0;
  1007.       Files[fnum].pos = -1;
  1008.       Files[fnum].open = True;
  1009.       Files[fnum].mmap_ptr = NULL;
  1010.       Files[fnum].mmap_size = 0;
  1011.       Files[fnum].can_lock = True;
  1012.       Files[fnum].can_read = ((flags & O_WRONLY)==0);
  1013.       Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
  1014.       Files[fnum].share_mode = 0;
  1015.       Files[fnum].share_pending = False;
  1016.       Files[fnum].print_file = Connections[cnum].printer;
  1017.       Files[fnum].cnum = cnum;
  1018.       string_set(&Files[fnum].name,fname);
  1019.       Files[fnum].wbmpx_ptr = NULL;      
  1020.  
  1021.       /*
  1022.        * If the printer is marked as postscript output a leading
  1023.        * file identifier to ensure the file is treated as a raw
  1024.        * postscript file.
  1025.        * This has a similar effect as CtrlD=0 in WIN.INI file.
  1026.        * tim@fsg.com 09/06/94
  1027.        */
  1028.       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
  1029.       Files[fnum].can_write) 
  1030.     {
  1031.       DEBUG(3,("Writing postscript line\n"));
  1032.       write_data(Files[fnum].fd,"%!\n",3);
  1033.     }
  1034.       
  1035.       DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
  1036.            timestring(),Connections[cnum].user,fname,
  1037.            BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
  1038.            Connections[cnum].num_files_open,fnum));
  1039.  
  1040.     }
  1041.  
  1042. #if USE_MMAP
  1043.   /* mmap it if read-only */
  1044.   if (!Files[fnum].can_write)
  1045.     {
  1046.       Files[fnum].mmap_size = file_size(fname);
  1047.       Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
  1048.                       PROT_READ,MAP_SHARED,Files[fnum].fd,0);
  1049.  
  1050.       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
  1051.     {
  1052.       DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
  1053.       Files[fnum].mmap_ptr = NULL;
  1054.     }
  1055.     }
  1056. #endif
  1057. }
  1058.  
  1059. /*******************************************************************
  1060. sync a file
  1061. ********************************************************************/
  1062. void sync_file(int fnum)
  1063. {
  1064. #ifndef NO_FSYNC
  1065.   fsync(Files[fnum].fd);
  1066. #endif
  1067. }
  1068.  
  1069. /****************************************************************************
  1070. run a file if it is a magic script
  1071. ****************************************************************************/
  1072. static void check_magic(int fnum,int cnum)
  1073. {
  1074.   if (!*lp_magicscript(SNUM(cnum)))
  1075.     return;
  1076.  
  1077.   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
  1078.  
  1079.   {
  1080.     char *p;
  1081.     if (!(p = strrchr(Files[fnum].name,'/')))
  1082.       p = Files[fnum].name;
  1083.     else
  1084.       p++;
  1085.  
  1086.     if (!strequal(lp_magicscript(SNUM(cnum)),p))
  1087.       return;
  1088.   }
  1089.  
  1090.   {
  1091.     int ret;
  1092.     pstring magic_output;
  1093.     pstring fname;
  1094.     strcpy(fname,Files[fnum].name);
  1095.  
  1096.     if (*lp_magicoutput(SNUM(cnum)))
  1097.       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
  1098.     else
  1099.       sprintf(magic_output,"%s.out",fname);
  1100.  
  1101.     chmod(fname,0755);
  1102.     ret = smbrun(fname,magic_output);
  1103.     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
  1104.     unlink(fname);
  1105.   }
  1106. }
  1107.  
  1108.  
  1109. /****************************************************************************
  1110. close a file - possibly invalidating the read prediction
  1111. ****************************************************************************/
  1112. void close_file(int fnum)
  1113. {
  1114.   int cnum = Files[fnum].cnum;
  1115.   invalidate_read_prediction(Files[fnum].fd);
  1116.   Files[fnum].open = False;
  1117.   Connections[cnum].num_files_open--;
  1118.   if(Files[fnum].wbmpx_ptr) 
  1119.     {
  1120.       free((char *)Files[fnum].wbmpx_ptr);
  1121.       Files[fnum].wbmpx_ptr = NULL;
  1122.     }
  1123.  
  1124. #if USE_MMAP
  1125.   if(Files[fnum].mmap_ptr) 
  1126.     {
  1127.       munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
  1128.       Files[fnum].mmap_ptr = NULL;
  1129.     }
  1130. #endif
  1131.  
  1132.   if (lp_share_modes(SNUM(cnum)))
  1133.     del_share_mode(fnum);
  1134.  
  1135.   close(Files[fnum].fd);
  1136.  
  1137.   /* NT uses smbclose to start a print - weird */
  1138.   if (Files[fnum].print_file)
  1139.     print_file(fnum);
  1140.  
  1141.   /* check for magic scripts */
  1142.   check_magic(fnum,cnum);
  1143.  
  1144.   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
  1145.        timestring(),Connections[cnum].user,Files[fnum].name,
  1146.        Connections[cnum].num_files_open));
  1147. }
  1148.  
  1149. enum {AFAIL,AREAD,AWRITE,AALL};
  1150.  
  1151. /*******************************************************************
  1152. reproduce the share mode access table
  1153. ********************************************************************/
  1154. static int access_table(int new_deny,int old_deny,int old_mode)
  1155. {
  1156.   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
  1157.  
  1158.   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
  1159.     if (old_mode == 0) return(AREAD);
  1160.     return(AFAIL);
  1161.   }
  1162.  
  1163.   switch (new_deny) 
  1164.     {
  1165.     case DENY_WRITE:
  1166.       if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
  1167.       if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
  1168.       if (old_deny==DENY_NONE && old_mode==0) return(AALL);
  1169.       return(AFAIL);
  1170.     case DENY_READ:
  1171.       if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
  1172.       if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
  1173.       if (old_deny==DENY_NONE && old_mode==1) return(AALL);
  1174.       return(AFAIL);
  1175.     case DENY_NONE:
  1176.       if (old_deny==DENY_WRITE) return(AREAD);
  1177.       if (old_deny==DENY_READ) return(AWRITE);
  1178.       if (old_deny==DENY_NONE) return(AALL);
  1179.       return(AFAIL);      
  1180.     }
  1181.   return(AFAIL);      
  1182. }
  1183.  
  1184. /*******************************************************************
  1185. check if the share mode on a file allows it to be deleted or unlinked
  1186. return True if sharing doesn't prevent the operation
  1187. ********************************************************************/
  1188. BOOL check_file_sharing(int cnum,char *fname)
  1189. {
  1190.   int pid=0;
  1191.   int share_mode = get_share_mode_byname(cnum,fname,&pid);
  1192.  
  1193.   if (!pid || !share_mode) return(True);
  1194.  
  1195.   if (share_mode == DENY_DOS)
  1196.     return(pid == getpid());
  1197.  
  1198.   /* XXXX exactly what share mode combinations should be allowed for
  1199.      deleting/renaming? */
  1200.   return(False);
  1201. }
  1202.  
  1203. /****************************************************************************
  1204.   C. Hoch 11/22/95
  1205.   Helper for open_file_shared. 
  1206.   Truncate a file after checking locking; close file if locked.
  1207.   **************************************************************************/
  1208. static void truncate_unless_locked(int fnum, int cnum)
  1209. {
  1210.   if (Files[fnum].can_write){
  1211.     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
  1212.       close_file(fnum);   
  1213.       errno = EACCES;
  1214.       unix_ERR_class = ERRDOS;
  1215.       unix_ERR_code = ERRlock;
  1216.     }
  1217.     else
  1218.       ftruncate(Files[fnum].fd,0); 
  1219.   }
  1220. }
  1221.  
  1222.  
  1223. /****************************************************************************
  1224. open a file with a share mode
  1225. ****************************************************************************/
  1226. void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
  1227.               int mode,int *Access,int *action)
  1228. {
  1229.   int flags=0;
  1230.   int flags2=0;
  1231.   int deny_mode = (share_mode>>4)&7;
  1232.   struct stat sbuf;
  1233.   BOOL file_existed = file_exist(fname,&sbuf);
  1234.   BOOL fcbopen = False;
  1235.   int share_pid=0;
  1236.  
  1237.   Files[fnum].open = False;
  1238.   Files[fnum].fd = -1;
  1239.  
  1240.   /* this is for OS/2 EAs - try and say we don't support them */
  1241.   if (strstr(fname,".+,;=[].")) {
  1242.     unix_ERR_class = ERRDOS;
  1243.     unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
  1244.     return;
  1245.   }
  1246.  
  1247.   if ((ofun & 0x3) == 0 && file_existed) {
  1248.     errno = EEXIST;
  1249.     return;
  1250.   }
  1251.       
  1252.   if (ofun & 0x10)
  1253.     flags2 |= O_CREAT;
  1254.   if ((ofun & 0x3) == 2)
  1255.     flags2 |= O_TRUNC;
  1256.  
  1257.   /* note that we ignore the append flag as 
  1258.      append does not mean the same thing under dos and unix */
  1259.  
  1260.   switch (share_mode&0xF)
  1261.     {
  1262.     case 1: 
  1263.       flags = O_WRONLY; 
  1264.       break;
  1265.     case 0xF: 
  1266.       fcbopen = True;
  1267.       flags = O_RDWR; 
  1268.       break;
  1269.     case 2: 
  1270.       flags = O_RDWR; 
  1271.       break;
  1272.     default:
  1273.       flags = O_RDONLY;
  1274.       break;
  1275.     }
  1276.   
  1277.   if (flags != O_RDONLY && file_existed && 
  1278.       (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
  1279.     if (!fcbopen) {
  1280.       errno = EACCES;
  1281.       return;
  1282.     }
  1283.     flags = O_RDONLY;
  1284.   }
  1285.  
  1286.   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
  1287.     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
  1288.     errno = EINVAL;
  1289.     return;
  1290.   }
  1291.  
  1292.   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
  1293.  
  1294.   if (lp_share_modes(SNUM(cnum))) {
  1295.     int old_share=0;
  1296.  
  1297.     if (file_existed)
  1298.       old_share = get_share_mode(cnum,&sbuf,&share_pid);
  1299.  
  1300.     if (share_pid) {
  1301.       /* someone else has a share lock on it, check to see 
  1302.      if we can too */
  1303.       int old_open_mode = old_share&0xF;
  1304.       int old_deny_mode = (old_share>>4)&7;
  1305.  
  1306.       if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
  1307.     DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
  1308.          deny_mode,old_deny_mode,old_open_mode,fname));
  1309.     errno = EACCES;
  1310.     unix_ERR_class = ERRDOS;
  1311.     unix_ERR_code = ERRbadshare;
  1312.     return;
  1313.       }
  1314.  
  1315.       /* C. Hoch 11/21/95 Handle DOS (compatibility) mode on the same machine.
  1316.        * Any number of read and/or write opens in compatibility mode from the 
  1317.        * same machine are allowed.
  1318.        * Also, read opens in compatibility mode from different machines
  1319.        * are allowed, even if the file is already opened for read in some
  1320.        * share mode. This is "soft compatibility" mode (Microsoft Knowledge Base,
  1321.        * WfWG, "How VSHARE386 Manages File Sharing", Q90239), and is handled in
  1322.        * access_table().
  1323.        */
  1324.       if ((deny_mode==DENY_DOS || old_deny_mode==DENY_DOS) && 
  1325.       share_pid == getpid()) {
  1326.     if (old_deny_mode != deny_mode) {
  1327.       DEBUG(2,("Share violation on file %s\n",fname));
  1328.       errno = EACCES;
  1329.       unix_ERR_class = ERRDOS;
  1330.       unix_ERR_code = ERRbadshare;
  1331.       return;
  1332.     }
  1333.       } else {
  1334.     int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode);
  1335.  
  1336.     if ((access_allowed == AFAIL) ||
  1337.         (access_allowed == AREAD && flags == O_WRONLY) ||
  1338.         (access_allowed == AWRITE && flags == O_RDONLY)) {
  1339.       DEBUG(2,("Share violation on file %s\n",fname));
  1340.       errno = EACCES;
  1341.       unix_ERR_class = ERRDOS;
  1342.       unix_ERR_code = ERRbadshare;
  1343.       return;
  1344.     }
  1345.     
  1346.     if (access_allowed == AREAD)
  1347.       flags = O_RDONLY;
  1348.     
  1349.     if (access_allowed == AWRITE)
  1350.       flags = O_WRONLY;
  1351.       }
  1352.     }
  1353.   }
  1354.  
  1355.   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
  1356.        flags,flags2,mode));
  1357.  
  1358.   open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode);
  1359.   if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
  1360.     flags = O_RDONLY;
  1361.     open_file(fnum,cnum,fname,flags,mode);
  1362.   }
  1363.  
  1364.   if (Files[fnum].open) {
  1365.     int open_mode;
  1366.     switch (flags) {
  1367.     case O_RDONLY:
  1368.       open_mode = 0;
  1369.       break;
  1370.     case O_RDWR:
  1371.       open_mode = 2;
  1372.       break;
  1373.     case O_WRONLY:
  1374.       open_mode = 1;
  1375.       break;
  1376.     }
  1377.  
  1378.     Files[fnum].share_mode = (deny_mode<<4) | open_mode;
  1379.     Files[fnum].share_pending = True;
  1380.  
  1381.     if (Access) {
  1382.       (*Access) = open_mode;
  1383.     }
  1384.     
  1385.     if (action) {
  1386.       if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
  1387.       if (!file_existed) *action = 2;
  1388.       if (file_existed && (flags2 & O_TRUNC)) *action = 3;
  1389.     }
  1390.  
  1391.     if (!share_pid)
  1392.       share_mode_pending = True;
  1393.  
  1394.     if ((flags2&O_TRUNC) && file_existed)
  1395.       truncate_unless_locked(fnum,cnum);
  1396.   }
  1397. }
  1398.  
  1399.  
  1400.  
  1401. /*******************************************************************
  1402. check for files that we should now set our share modes on
  1403. ********************************************************************/
  1404. static void check_share_modes(void)
  1405. {
  1406.   int i;
  1407.   for (i=0;i<MAX_OPEN_FILES;i++)
  1408.     if(Files[i].open && Files[i].share_pending) {
  1409.       if (lp_share_modes(SNUM(Files[i].cnum))) {
  1410.     int pid=0;
  1411.     get_share_mode_by_fnum(Files[i].cnum,i,&pid);
  1412.     if (!pid) {
  1413.       set_share_mode(i,Files[i].share_mode);
  1414.       Files[i].share_pending = False;
  1415.     }
  1416.       } else {
  1417.     Files[i].share_pending = False;    
  1418.       }
  1419.     }
  1420. }
  1421.  
  1422.  
  1423. /****************************************************************************
  1424. seek a file. Try to avoid the seek if possible
  1425. ****************************************************************************/
  1426. int seek_file(int fnum,int pos)
  1427. {
  1428.   int offset = 0;
  1429.   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
  1430.     offset = 3;
  1431.  
  1432.   Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
  1433.   return(Files[fnum].pos);
  1434. }
  1435.  
  1436. /****************************************************************************
  1437. read from a file
  1438. ****************************************************************************/
  1439. int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
  1440. {
  1441.   int ret=0;
  1442.  
  1443.   if (!Files[fnum].can_write)
  1444.     {
  1445.       ret = read_predict(Files[fnum].fd,
  1446.              pos,
  1447.              data,
  1448.              NULL,
  1449.              maxcnt);
  1450.  
  1451.       data += ret;
  1452.       maxcnt -= ret;
  1453.       mincnt = MAX(mincnt-ret,0);
  1454.       pos += ret;
  1455.     }
  1456.  
  1457. #if USE_MMAP
  1458.   if (Files[fnum].mmap_ptr)
  1459.     {
  1460.       int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
  1461.       if (num > 0)
  1462.     {
  1463.       memcpy(data,Files[fnum].mmap_ptr+pos,num);
  1464.       data += num;
  1465.       pos += num;
  1466.       maxcnt -= num;
  1467.       mincnt = MAX(mincnt-num,0);
  1468.       ret += num;
  1469.     }
  1470.     }
  1471. #endif
  1472.  
  1473.   if (maxcnt <= 0)
  1474.     return(ret);
  1475.  
  1476.   if (seek_file(fnum,pos) != pos)
  1477.     {
  1478.       DEBUG(3,("Failed to seek to %d\n",pos));
  1479.       return(ret);
  1480.     }
  1481.   
  1482.   if (maxcnt > 0)
  1483.     ret += read_with_timeout(Files[fnum].fd,
  1484.                  data,
  1485.                  mincnt,
  1486.                  maxcnt,
  1487.                  timeout,
  1488.                  exact);
  1489.  
  1490.   return(ret);
  1491. }
  1492.  
  1493.  
  1494. static int old_umask = 022;
  1495.  
  1496. /****************************************************************************
  1497. load parameters specific to a connection/service
  1498. ****************************************************************************/
  1499. BOOL become_service(int cnum,BOOL do_chdir)
  1500. {
  1501.   extern char magic_char;
  1502.   static int last_cnum = -1;
  1503.   int snum;
  1504.  
  1505.   if (!OPEN_CNUM(cnum))
  1506.     {
  1507.       last_cnum = -1;
  1508.       return(False);
  1509.     }
  1510.  
  1511.   Connections[cnum].lastused = smb_last_time;
  1512.  
  1513.   snum = SNUM(cnum);
  1514.   
  1515.   if (do_chdir &&
  1516.       ChDir(Connections[cnum].connectpath) != 0 &&
  1517.       ChDir(Connections[cnum].origpath) != 0)
  1518.     {
  1519.       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
  1520.         Connections[cnum].connectpath,cnum));     
  1521.       return(False);
  1522.     }
  1523.  
  1524.   if (cnum == last_cnum)
  1525.     return(True);
  1526.  
  1527.   last_cnum = cnum;
  1528.  
  1529.   case_default = lp_defaultcase(snum);
  1530.   case_preserve = lp_preservecase(snum);
  1531.   short_case_preserve = lp_shortpreservecase(snum);
  1532.   case_mangle = lp_casemangle(snum);
  1533.   case_sensitive = lp_casesensitive(snum);
  1534.   magic_char = lp_magicchar(snum);
  1535.   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
  1536.   return(True);
  1537. }
  1538.  
  1539.  
  1540. /****************************************************************************
  1541.   become the specified uid 
  1542. ****************************************************************************/
  1543. static BOOL become_uid(int uid)
  1544. {
  1545.   if (initial_uid != 0)
  1546.     return(True);
  1547.  
  1548. #ifdef AIX
  1549.   {
  1550.     /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
  1551.     priv_t priv;
  1552.  
  1553.     priv.pv_priv[0] = 0;
  1554.     priv.pv_priv[1] = 0;
  1555.     if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
  1556.         &priv, sizeof(priv_t)) < 0 ||
  1557.     setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 ||
  1558.     seteuid((uid_t)uid) < 0) 
  1559.       DEBUG(1,("Can't set uid (AIX3)"));
  1560.   }
  1561. #endif
  1562.  
  1563. #ifdef USE_SETRES
  1564.   if (setresuid(-1,uid,-1) != 0)
  1565. #else
  1566.     if ((seteuid(uid) != 0) && 
  1567.     (setuid(uid) != 0))
  1568. #endif
  1569.       {
  1570.     DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
  1571.          uid,getuid(), geteuid()));
  1572.     if (uid > 32000)
  1573.       DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
  1574.     return(False);
  1575.       }
  1576.  
  1577.   if (((uid == -1) || (uid == 65535)) && geteuid() != uid)
  1578.     {
  1579.       DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
  1580.       return(False);
  1581.     }
  1582.  
  1583.   return(True);
  1584. }
  1585.  
  1586.  
  1587. /****************************************************************************
  1588.   become the specified gid
  1589. ****************************************************************************/
  1590. static BOOL become_gid(int gid)
  1591. {
  1592.   if (initial_uid != 0)
  1593.     return(True);
  1594.   
  1595. #ifdef USE_SETRES 
  1596.   if (setresgid(-1,gid,-1) != 0)
  1597. #else
  1598.     if (setgid(gid) != 0)
  1599. #endif
  1600.       {
  1601.     DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
  1602.          gid,getgid(),getegid()));
  1603.     if (gid > 32000)
  1604.       DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
  1605.     return(False);
  1606.       }
  1607.  
  1608.   return(True);
  1609. }
  1610.  
  1611.  
  1612. /****************************************************************************
  1613.   become the specified uid and gid
  1614. ****************************************************************************/
  1615. static BOOL become_id(int uid,int gid)
  1616. {
  1617.   return(become_gid(gid) && become_uid(uid));
  1618. }
  1619.  
  1620. /****************************************************************************
  1621. become the guest user
  1622. ****************************************************************************/
  1623. static BOOL become_guest(void)
  1624. {
  1625.   BOOL ret;
  1626.   static struct passwd *pass=NULL;
  1627.  
  1628.   if (initial_uid != 0) 
  1629.     return(True);
  1630.  
  1631.   if (!pass)
  1632.     pass = Get_Pwnam(lp_guestaccount(-1),True);
  1633.   if (!pass) return(False);
  1634.  
  1635.   ret = become_id(pass->pw_uid,pass->pw_gid);
  1636.  
  1637.   if (!ret)
  1638.     DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
  1639.  
  1640.   last_user.cnum = -2;
  1641.  
  1642.   return(ret);
  1643. }
  1644.  
  1645. /*******************************************************************
  1646. check if a username is OK
  1647. ********************************************************************/
  1648. static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
  1649. {
  1650.   int i;
  1651.   for (i=0;i<Connections[cnum].uid_cache.entries;i++)
  1652.     if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True);
  1653.  
  1654.   if (!user_ok(vuser->name,snum)) return(False);
  1655.  
  1656.   i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
  1657.   Connections[cnum].uid_cache.list[i] = vuser->uid;
  1658.  
  1659.   if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
  1660.     Connections[cnum].uid_cache.entries++;
  1661.  
  1662.   return(True);
  1663. }
  1664.  
  1665.  
  1666. /****************************************************************************
  1667.   become the user of a connection number
  1668. ****************************************************************************/
  1669. BOOL become_user(int cnum, int uid)
  1670. {
  1671.   int new_umask;
  1672.   user_struct *vuser;
  1673.   int snum,gid;
  1674.   int ngroups;
  1675.   gid_t *groups;
  1676.  
  1677.   if (last_user.cnum == cnum && last_user.uid == uid) {
  1678.     DEBUG(4,("Skipping become_user - already user\n"));
  1679.     return(True);
  1680.   }
  1681.  
  1682.   unbecome_user();
  1683.  
  1684.   if (!OPEN_CNUM(cnum)) {
  1685.     DEBUG(2,("Connection %d not open\n",cnum));
  1686.     return(False);
  1687.   }
  1688.  
  1689.   snum = Connections[cnum].service;
  1690.  
  1691.   if (Connections[cnum].force_user || 
  1692.       lp_security() == SEC_SHARE ||
  1693.       !(vuser = get_valid_user_struct(uid)) ||
  1694.       !check_user_ok(cnum,vuser,snum)) {
  1695.     uid = Connections[cnum].uid;
  1696.     gid = Connections[cnum].gid;
  1697.     groups = Connections[cnum].groups;
  1698.     ngroups = Connections[cnum].ngroups;
  1699.   } else {
  1700.     if (!vuser) {
  1701.       DEBUG(2,("Invalid vuid used %d\n",uid));
  1702.       return(False);
  1703.     }
  1704.     uid = vuser->uid;
  1705.     if(!*lp_force_group(snum))
  1706.       gid = vuser->gid;
  1707.     else
  1708.       gid = Connections[cnum].gid;
  1709.     groups = vuser->user_groups;
  1710.     ngroups = vuser->user_ngroups;
  1711.   }
  1712.  
  1713.   if (initial_uid == 0)
  1714.     {
  1715.       if (!become_gid(gid)) return(False);
  1716.  
  1717. #ifndef NO_SETGROUPS      
  1718.       if (!IS_IPC(cnum)) {
  1719.     /* groups stuff added by ih/wreu */
  1720.     if (ngroups > 0)
  1721.       if (setgroups(ngroups,groups)<0)
  1722.         DEBUG(0,("setgroups call failed!\n"));
  1723.       }
  1724. #endif
  1725.  
  1726.       if (!Connections[cnum].admin_user && !become_uid(uid))
  1727.     return(False);
  1728.     }
  1729.  
  1730.   new_umask = 0777 & ~CREATE_MODE(cnum);
  1731.   old_umask = umask(new_umask);
  1732.  
  1733.   last_user.cnum = cnum;
  1734.   last_user.uid = uid;
  1735.   
  1736.   DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
  1737.        getuid(),geteuid(),getgid(),getegid(),new_umask));
  1738.   
  1739.   return(True);
  1740. }
  1741.  
  1742. /****************************************************************************
  1743.   unbecome the user of a connection number
  1744. ****************************************************************************/
  1745. BOOL unbecome_user(void )
  1746. {
  1747.   if (last_user.cnum == -1)
  1748.     return(False);
  1749.  
  1750.   ChDir(OriginalDir);
  1751.  
  1752.   umask(old_umask);
  1753.  
  1754.   if (initial_uid == 0)
  1755.     {
  1756. #ifdef USE_SETRES
  1757.       setresuid(-1,getuid(),-1);
  1758.       setresgid(-1,getgid(),-1);
  1759. #else
  1760.       if (seteuid(initial_uid) != 0) 
  1761.     setuid(initial_uid);
  1762.       setgid(initial_gid);
  1763. #endif
  1764.     }
  1765. #ifdef NO_EID
  1766.   if (initial_uid == 0)
  1767.     DEBUG(2,("Running with no EID\n"));
  1768.   initial_uid = getuid();
  1769.   initial_gid = getgid();
  1770. #else
  1771.   if (geteuid() != initial_uid)
  1772.     {
  1773.       DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
  1774.       initial_uid = geteuid();
  1775.     }
  1776.   if (getegid() != initial_gid)
  1777.     {
  1778.       DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
  1779.       initial_gid = getegid();
  1780.     }
  1781. #endif
  1782.   
  1783.   if (ChDir(OriginalDir) != 0)
  1784.     DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
  1785.          timestring(),OriginalDir));  
  1786.  
  1787.   DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
  1788.     getuid(),geteuid(),getgid(),getegid()));
  1789.  
  1790.   last_user.cnum = -1;
  1791.  
  1792.   return(True);
  1793. }
  1794.  
  1795. /****************************************************************************
  1796.   find a service entry
  1797. ****************************************************************************/
  1798. int find_service(char *service)
  1799. {
  1800.    int iService;
  1801.  
  1802.    string_sub(service,"\\","/");
  1803.  
  1804.    iService = lp_servicenumber(service);
  1805.  
  1806.    /* now handle the special case of a home directory */
  1807.    if (iService < 0)
  1808.    {
  1809.       char *phome_dir = get_home_dir(service);
  1810.       DEBUG(3,("checking for home directory %s gave %s\n",service,
  1811.         phome_dir?phome_dir:"(NULL)"));
  1812.       if (phome_dir)
  1813.       {   
  1814.      int iHomeService;
  1815.      if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
  1816.      {
  1817.         lp_add_home(service,iHomeService,phome_dir);
  1818.         iService = lp_servicenumber(service);
  1819.      }
  1820.       }
  1821.    }
  1822.  
  1823.    /* If we still don't have a service, attempt to add it as a printer. */
  1824.    if (iService < 0)
  1825.    {
  1826.       int iPrinterService;
  1827.  
  1828.       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
  1829.       {
  1830.          char *pszTemp;
  1831.  
  1832.          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
  1833.          pszTemp = PRINTCAP;
  1834.          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
  1835.          {
  1836.             DEBUG(3,("%s is a valid printer name\n", service));
  1837.             DEBUG(3,("adding %s as a printer service\n", service));
  1838.             lp_add_printer(service,iPrinterService);
  1839.             iService = lp_servicenumber(service);
  1840.             if (iService < 0)
  1841.                DEBUG(0,("failed to add %s as a printer service!\n", service));
  1842.          }
  1843.          else
  1844.             DEBUG(3,("%s is not a valid printer name\n", service));
  1845.       }
  1846.    }
  1847.  
  1848.    /* just possibly it's a default service? */
  1849.    if (iService < 0) 
  1850.      {
  1851.        char *defservice = lp_defaultservice();
  1852.        if (defservice && *defservice && !strequal(defservice,service)) {
  1853.      iService = find_service(defservice);
  1854.      if (iService >= 0) {
  1855.        string_sub(service,"_","/");
  1856.        iService = lp_add_service(service,iService);
  1857.      }
  1858.        }
  1859.      }
  1860.  
  1861.    if (iService >= 0)
  1862.       if (!VALID_SNUM(iService))
  1863.       {
  1864.          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
  1865.      iService = -1;
  1866.       }
  1867.  
  1868.    if (iService < 0)
  1869.       DEBUG(3,("find_service() failed to find service %s\n", service));
  1870.  
  1871.    return (iService);
  1872. }
  1873.  
  1874.  
  1875. /****************************************************************************
  1876.   create an error packet from a cached error.
  1877. ****************************************************************************/
  1878. int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
  1879. {
  1880.   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
  1881.  
  1882.   int32 eclass = wbmpx->wr_errclass;
  1883.   int32 err = wbmpx->wr_error;
  1884.  
  1885.   /* We can now delete the auxiliary struct */
  1886.   free((char *)wbmpx);
  1887.   Files[fnum].wbmpx_ptr = NULL;
  1888.   return error_packet(inbuf,outbuf,eclass,err,line);
  1889. }
  1890.  
  1891.  
  1892. struct
  1893. {
  1894.   int unixerror;
  1895.   int smbclass;
  1896.   int smbcode;
  1897. } unix_smb_errmap[] =
  1898. {
  1899.   {EPERM,ERRDOS,ERRnoaccess},
  1900.   {EACCES,ERRDOS,ERRnoaccess},
  1901.   {ENOENT,ERRDOS,ERRbadfile},
  1902.   {EIO,ERRHRD,ERRgeneral},
  1903.   {EBADF,ERRSRV,ERRsrverror},
  1904.   {EINVAL,ERRSRV,ERRsrverror},
  1905.   {EEXIST,ERRDOS,ERRfilexists},
  1906.   {ENFILE,ERRDOS,ERRnofids},
  1907.   {EMFILE,ERRDOS,ERRnofids},
  1908.   {ENOSPC,ERRHRD,ERRdiskfull},
  1909. #ifdef EDQUOT
  1910.   {EDQUOT,ERRHRD,ERRdiskfull},
  1911. #endif
  1912. #ifdef ENOTEMPTY
  1913.   {ENOTEMPTY,ERRDOS,ERRnoaccess},
  1914. #endif
  1915. #ifdef EXDEV
  1916.   {EXDEV,ERRDOS,ERRdiffdevice},
  1917. #endif
  1918.   {EROFS,ERRHRD,ERRnowrite},
  1919.   {0,0,0}
  1920. };
  1921.  
  1922.  
  1923. /****************************************************************************
  1924.   create an error packet from errno
  1925. ****************************************************************************/
  1926. int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
  1927. {
  1928.   int eclass=def_class;
  1929.   int ecode=def_code;
  1930.   int i=0;
  1931.  
  1932.   if (unix_ERR_class != SUCCESS)
  1933.     {
  1934.       eclass = unix_ERR_class;
  1935.       ecode = unix_ERR_code;
  1936.       unix_ERR_class = SUCCESS;
  1937.       unix_ERR_code = 0;
  1938.     }
  1939.   else
  1940.     {
  1941.       while (unix_smb_errmap[i].smbclass != 0)
  1942.     {
  1943.       if (unix_smb_errmap[i].unixerror == errno)
  1944.         {
  1945.           eclass = unix_smb_errmap[i].smbclass;
  1946.           ecode = unix_smb_errmap[i].smbcode;
  1947.           break;
  1948.         }
  1949.       i++;
  1950.     }
  1951.     }
  1952.  
  1953.   return(error_packet(inbuf,outbuf,eclass,ecode,line));
  1954. }
  1955.  
  1956.  
  1957. /****************************************************************************
  1958.   create an error packet. Normally called using the ERROR() macro
  1959. ****************************************************************************/
  1960. int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
  1961. {
  1962.   int outsize = set_message(outbuf,0,0,True);
  1963.   int cmd;
  1964.   cmd = CVAL(inbuf,smb_com);
  1965.   
  1966.   CVAL(outbuf,smb_rcls) = error_class;
  1967.   SSVAL(outbuf,smb_err,error_code);  
  1968.   
  1969.   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
  1970.        timestring(),
  1971.        line,
  1972.        (int)CVAL(inbuf,smb_com),
  1973.        smb_fn_name(CVAL(inbuf,smb_com)),
  1974.        error_class,
  1975.        error_code));
  1976.  
  1977.   if (errno != 0)
  1978.     DEBUG(3,("error string = %s\n",strerror(errno)));
  1979.   
  1980.   return(outsize);
  1981. }
  1982.  
  1983.  
  1984. #ifndef SIGCLD_IGNORE
  1985. /****************************************************************************
  1986. this prevents zombie child processes
  1987. ****************************************************************************/
  1988. static int sig_cld()
  1989. {
  1990.   static int depth = 0;
  1991.   if (depth != 0)
  1992.     {
  1993.       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
  1994.       depth=0;
  1995.       return(0);
  1996.     }
  1997.   depth++;
  1998.  
  1999.   BlockSignals(True);
  2000.   DEBUG(5,("got SIGCLD\n"));
  2001.  
  2002. #ifdef USE_WAITPID
  2003.   while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
  2004. #endif
  2005.  
  2006.   /* Stop zombies */
  2007.   /* Stevens, Adv. Unix Prog. says that on system V you must call
  2008.      wait before reinstalling the signal handler, because the kernel
  2009.      calls the handler from within the signal-call when there is a
  2010.      child that has exited. This would lead to an infinite recursion
  2011.      if done vice versa. */
  2012.         
  2013. #ifndef DONT_REINSTALL_SIG
  2014. #ifdef SIGCLD_IGNORE
  2015.   signal(SIGCLD, SIG_IGN);  
  2016. #else
  2017.   signal(SIGCLD, SIGNAL_CAST sig_cld);
  2018. #endif
  2019. #endif
  2020.  
  2021. #ifndef USE_WAITPID
  2022.   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
  2023. #endif
  2024.   depth--;
  2025.   BlockSignals(False);
  2026.   return 0;
  2027. }
  2028. #endif
  2029.  
  2030. /****************************************************************************
  2031.   this is called when the client exits abruptly
  2032.   **************************************************************************/
  2033. static int sig_pipe()
  2034. {
  2035.   exit_server("Got sigpipe\n");
  2036.   return(0);
  2037. }
  2038.  
  2039. /****************************************************************************
  2040.   open the socket communication
  2041. ****************************************************************************/
  2042. static BOOL open_sockets(BOOL is_daemon,int port)
  2043. {
  2044.   extern int Client;
  2045.  
  2046.   if (is_daemon)
  2047.     {
  2048.       int s;
  2049.       struct sockaddr addr;
  2050.       int in_addrlen = sizeof(addr);
  2051.        
  2052.       /* Stop zombies */
  2053. #ifdef SIGCLD_IGNORE
  2054.       signal(SIGCLD, SIG_IGN);
  2055. #else
  2056.       signal(SIGCLD, SIGNAL_CAST sig_cld);
  2057. #endif
  2058.  
  2059.       /* open an incoming socket */
  2060.       s = open_socket_in(SOCK_STREAM, port, 0);
  2061.       if (s == -1)
  2062.     return(False);
  2063.  
  2064.       /* ready to listen */
  2065.       if (listen(s, 5) == -1) 
  2066.     {
  2067.       DEBUG(0,("listen: %s",strerror(errno)));
  2068.       close(s);
  2069.       return False;
  2070.     }
  2071.       
  2072.       /* now accept incoming connections - forking a new process
  2073.      for each incoming connection */
  2074.       DEBUG(2,("waiting for a connection\n"));
  2075.       while (1)
  2076.     {
  2077.       Client = accept(s,&addr,&in_addrlen);
  2078.  
  2079.       if (Client == -1 && errno == EINTR)
  2080.         continue;
  2081.  
  2082.       if (Client == -1)
  2083.         {
  2084.           DEBUG(0,("accept: %s",strerror(errno)));
  2085.           return False;
  2086.         }
  2087.  
  2088. #ifdef NO_FORK_DEBUG
  2089. #ifndef NO_SIGNAL_TEST
  2090.           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2091.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  2092. #endif
  2093.       return True;
  2094. #else
  2095.       if (Client != -1 && fork()==0)
  2096.         {
  2097. #ifndef NO_SIGNAL_TEST
  2098.           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2099.           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
  2100. #endif
  2101.           /* close our standard file descriptors */
  2102.           close_low_fds();
  2103.   
  2104.           set_socket_options(Client,"SO_KEEPALIVE");
  2105.           set_socket_options(Client,user_socket_options);
  2106.  
  2107.           return True; 
  2108.         }
  2109.           close(Client); /* The parent doesn't need this socket */
  2110. #endif
  2111.     }
  2112.     }
  2113.   else
  2114.     {
  2115.       /* We will abort gracefully when the client or remote system 
  2116.      goes away */
  2117. #ifndef NO_SIGNAL_TEST
  2118.       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  2119. #endif
  2120.       Client = dup(0);
  2121.  
  2122.       /* close our standard file descriptors */
  2123.       close_low_fds();
  2124.  
  2125.       set_socket_options(Client,"SO_KEEPALIVE");
  2126.       set_socket_options(Client,user_socket_options);
  2127.     }
  2128.  
  2129.   return True;
  2130. }
  2131.  
  2132.  
  2133. /****************************************************************************
  2134. check if a snum is in use
  2135. ****************************************************************************/
  2136. BOOL snum_used(int snum)
  2137. {
  2138.   int i;
  2139.   for (i=0;i<MAX_CONNECTIONS;i++)
  2140.     if (OPEN_CNUM(i) && (SNUM(i) == snum))
  2141.       return(True);
  2142.   return(False);
  2143. }
  2144.  
  2145. /****************************************************************************
  2146.   reload the services file
  2147.   **************************************************************************/
  2148. BOOL reload_services(BOOL test)
  2149. {
  2150.   BOOL ret;
  2151.  
  2152.   if (lp_loaded())
  2153.     {
  2154.       pstring fname;
  2155.       strcpy(fname,lp_configfile());
  2156.       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
  2157.     {
  2158.       strcpy(servicesf,fname);
  2159.       test = False;
  2160.     }
  2161.     }
  2162.  
  2163.   reopen_logs();
  2164.  
  2165.   if (test && !lp_file_list_changed())
  2166.     return(True);
  2167.  
  2168.   lp_killunused(snum_used);
  2169.  
  2170.   ret = lp_load(servicesf,False);
  2171.  
  2172.   /* perhaps the config filename is now set */
  2173.   if (!test)
  2174.     reload_services(True);
  2175.  
  2176.   reopen_logs();
  2177.  
  2178.   {
  2179.     extern int Client;
  2180.     if (Client != -1) {      
  2181.       set_socket_options(Client,"SO_KEEPALIVE");
  2182.       set_socket_options(Client,user_socket_options);
  2183.     }
  2184.   }
  2185.  
  2186.   create_mangled_stack(lp_mangledstack());
  2187.  
  2188.   /* this forces service parameters to be flushed */
  2189.   become_service(-1,True);
  2190.  
  2191.   return(ret);
  2192. }
  2193.  
  2194.  
  2195.  
  2196. /****************************************************************************
  2197. this prevents zombie child processes
  2198. ****************************************************************************/
  2199. static int sig_hup()
  2200. {
  2201.   BlockSignals(True);
  2202.   DEBUG(0,("Got SIGHUP\n"));
  2203.   reload_services(False);
  2204. #ifndef DONT_REINSTALL_SIG
  2205.   signal(SIGHUP,SIGNAL_CAST sig_hup);
  2206. #endif
  2207.   BlockSignals(False);
  2208.   return(0);
  2209. }
  2210.  
  2211. /****************************************************************************
  2212. Setup the groups a user belongs to.
  2213. ****************************************************************************/
  2214. int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
  2215.          int **p_igroups, gid_t **p_groups)
  2216. {
  2217.   if (-1 == initgroups(user,gid))
  2218.     {
  2219.       if (getuid() == 0)
  2220.     {
  2221.       DEBUG(0,("Unable to initgroups!\n"));
  2222.       if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
  2223.         DEBUG(0,("This is probably a problem with the account %s\n",user));
  2224.     }
  2225.     }
  2226.   else
  2227.     {
  2228.       int i,ngroups;
  2229.       int *igroups;
  2230.       gid_t grp = 0;
  2231.       ngroups = getgroups(0,&grp);
  2232.       if (ngroups <= 0)
  2233.         ngroups = 32;
  2234.       igroups = (int *)malloc(sizeof(int)*ngroups);
  2235.       for (i=0;i<ngroups;i++)
  2236.         igroups[i] = 0x42424242;
  2237.       ngroups = getgroups(ngroups,(gid_t *)igroups);
  2238.  
  2239.       if (igroups[0] == 0x42424242)
  2240.         ngroups = 0;
  2241.  
  2242.       *p_ngroups = ngroups;
  2243.  
  2244.       /* The following bit of code is very strange. It is due to the
  2245.          fact that some OSes use int* and some use gid_t* for
  2246.          getgroups, and some (like SunOS) use both, one in prototypes,
  2247.          and one in man pages and the actual code. Thus we detect it
  2248.          dynamically using some very ugly code */
  2249.       if (ngroups > 0)
  2250.         {
  2251.       /* does getgroups return ints or gid_t ?? */
  2252.       static BOOL groups_use_ints = True;
  2253.  
  2254.       if (groups_use_ints && 
  2255.           ngroups == 1 && 
  2256.           SVAL(igroups,2) == 0x4242)
  2257.         groups_use_ints = False;
  2258.       
  2259.           for (i=0;groups_use_ints && i<ngroups;i++)
  2260.             if (igroups[i] == 0x42424242)
  2261.               groups_use_ints = False;
  2262.           
  2263.           if (groups_use_ints)
  2264.             {
  2265.               *p_igroups = igroups;
  2266.               *p_groups = (gid_t *)igroups;      
  2267.             }
  2268.           else
  2269.             {
  2270.           gid_t *groups = (gid_t *)igroups;
  2271.           igroups = (int *)malloc(sizeof(int)*ngroups);
  2272.           for (i=0;i<ngroups;i++)
  2273.             igroups[i] = groups[i];
  2274.           *p_igroups = igroups;
  2275.           *p_groups = (gid_t *)groups;
  2276.         }
  2277.     }
  2278.       DEBUG(3,("%s is in %d groups\n",user,ngroups));
  2279.       for (i=0;i<ngroups;i++)
  2280.         DEBUG(3,("%d ",igroups[i]));
  2281.       DEBUG(3,("\n"));
  2282.     }
  2283.   return 0;
  2284. }
  2285.  
  2286. /****************************************************************************
  2287.   make a connection to a service
  2288. ****************************************************************************/
  2289. int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid)
  2290. {
  2291.   int cnum;
  2292.   int snum;
  2293.   struct passwd *pass = NULL;
  2294.   connection_struct *pcon;
  2295.   BOOL guest = False;
  2296.   BOOL force = False;
  2297.   static BOOL first_connection = True;
  2298.  
  2299.   strlower(service);
  2300.  
  2301.   snum = find_service(service);
  2302.   if (snum < 0)
  2303.     {
  2304.       if (strequal(service,"IPC$"))
  2305.     {      
  2306.       DEBUG(3,("%s refusing IPC connection\n",timestring()));
  2307.       return(-3);
  2308.     }
  2309.  
  2310.       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
  2311.       return(-2);
  2312.     }
  2313.  
  2314.   if (strequal(service,HOMES_NAME))
  2315.     {
  2316.       if (*user && Get_Pwnam(user,True))
  2317.     return(make_connection(user,user,password,pwlen,dev,vuid));
  2318.  
  2319.       if (validated_username(vuid))
  2320.     {
  2321.       strcpy(user,validated_username(vuid));
  2322.       return(make_connection(user,user,password,pwlen,dev,vuid));
  2323.     }
  2324.     }
  2325.  
  2326.   if (!lp_snum_ok(snum) || !check_access(snum)) {    
  2327.     return(-4);
  2328.   }
  2329.  
  2330.   /* you can only connect to the IPC$ service as an ipc device */
  2331.   if (strequal(service,"IPC$"))
  2332.     strcpy(dev,"IPC");
  2333.  
  2334.   if (*dev == '?' || !*dev)
  2335.     {
  2336.       if (lp_print_ok(snum))
  2337.     strcpy(dev,"LPT1:");
  2338.       else
  2339.     strcpy(dev,"A:");
  2340.     }
  2341.  
  2342.   /* if the request is as a printer and you can't print then refuse */
  2343.   strupper(dev);
  2344.   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
  2345.     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
  2346.     return(-6);
  2347.   }
  2348.  
  2349.   /* lowercase the user name */
  2350.   strlower(user);
  2351.  
  2352.   /* add it as a possible user name */
  2353.   add_session_user(service);
  2354.  
  2355.   /* shall we let them in? */
  2356.   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
  2357.     {
  2358.       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
  2359.       return(-1);
  2360.     }
  2361.   
  2362.   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
  2363.   if (cnum < 0)
  2364.     {
  2365.       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
  2366.       return(-1);
  2367.     }
  2368.  
  2369.   pcon = &Connections[cnum];
  2370.   bzero((char *)pcon,sizeof(*pcon));
  2371.  
  2372.   /* find out some info about the user */
  2373.   pass = Get_Pwnam(user,True);
  2374.  
  2375.   if (pass == NULL)
  2376.     {
  2377.       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
  2378.       return(-7);
  2379.     }
  2380.  
  2381.   pcon->read_only = lp_readonly(snum);
  2382.  
  2383.   {
  2384.     pstring list;
  2385.     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
  2386.     string_sub(list,"%S",service);
  2387.  
  2388.     if (user_in_list(user,list))
  2389.       pcon->read_only = True;
  2390.  
  2391.     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
  2392.     string_sub(list,"%S",service);
  2393.  
  2394.     if (user_in_list(user,list))
  2395.       pcon->read_only = False;    
  2396.   }
  2397.  
  2398.   /* admin user check */
  2399.   if (user_in_list(user,lp_admin_users(snum)) &&
  2400.       !pcon->read_only)
  2401.     {
  2402.       pcon->admin_user = True;
  2403.       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
  2404.     }
  2405.   else
  2406.     pcon->admin_user = False;
  2407.     
  2408.   pcon->force_user = force;
  2409.   pcon->uid = pass->pw_uid;
  2410.   pcon->gid = pass->pw_gid;
  2411.   pcon->num_files_open = 0;
  2412.   pcon->lastused = time(NULL);
  2413.   pcon->service = snum;
  2414.   pcon->used = True;
  2415.   pcon->printer = (strncmp(dev,"LPT",3) == 0);
  2416.   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
  2417.   pcon->dirptr = NULL;
  2418.   string_set(&pcon->dirpath,"");
  2419.   string_set(&pcon->user,user);
  2420.  
  2421. #if HAVE_GETGRNAM 
  2422.   if (*lp_force_group(snum))
  2423.     {
  2424.       struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
  2425.       if (gptr)
  2426.     {
  2427.       pcon->gid = gptr->gr_gid;
  2428.       DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
  2429.     }
  2430.       else
  2431.     DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
  2432.     }
  2433. #endif
  2434.  
  2435.   if (*lp_force_user(snum))
  2436.     {
  2437.       struct passwd *pass2;
  2438.       fstring fuser;
  2439.       strcpy(fuser,lp_force_user(snum));
  2440.       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
  2441.       if (pass2)
  2442.     {
  2443.       pcon->uid = pass2->pw_uid;
  2444.       string_set(&pcon->user,fuser);
  2445.       strcpy(user,fuser);
  2446.       pcon->force_user = True;
  2447.       DEBUG(3,("Forced user %s\n",fuser));      
  2448.     }
  2449.       else
  2450.     DEBUG(1,("Couldn't find user %s\n",fuser));
  2451.     }
  2452.  
  2453.   {
  2454.     pstring s;
  2455.     strcpy(s,lp_pathname(snum));
  2456.     standard_sub(cnum,s);
  2457.     string_set(&pcon->connectpath,s);
  2458.     DEBUG(3,("Connect path is %s\n",s));
  2459.   }
  2460.  
  2461.   /* groups stuff added by ih */
  2462.   pcon->ngroups = 0;
  2463.   pcon->groups = NULL;
  2464.  
  2465.   if (!IS_IPC(cnum))
  2466.     {
  2467.       /* Find all the groups this uid is in and store them. Used by become_user() */
  2468.       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
  2469.       
  2470.       /* check number of connections */
  2471.       if (!claim_connection(cnum,
  2472.                 lp_servicename(SNUM(cnum)),
  2473.                 lp_max_connections(SNUM(cnum)),False))
  2474.     {
  2475.       DEBUG(1,("too many connections - rejected\n"));
  2476.       return(-8);
  2477.     }  
  2478.  
  2479.       if (lp_status(SNUM(cnum)))
  2480.     claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
  2481.  
  2482.       first_connection = False;
  2483.     } /* IS_IPC */
  2484.  
  2485.   pcon->open = True;
  2486.  
  2487.   /* execute any "root preexec = " line */
  2488.   if (*lp_rootpreexec(SNUM(cnum)))
  2489.     {
  2490.       pstring cmd;
  2491.       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
  2492.       standard_sub(cnum,cmd);
  2493.       DEBUG(5,("cmd=%s\n",cmd));
  2494.       smbrun(cmd,NULL);
  2495.     }
  2496.  
  2497.   if (!become_user(cnum,pcon->uid))
  2498.     {
  2499.       DEBUG(0,("Can't become connected user!\n"));
  2500.       pcon->open = False;
  2501.       if (!IS_IPC(cnum)) {
  2502.     yield_connection(cnum,
  2503.              lp_servicename(SNUM(cnum)),
  2504.              lp_max_connections(SNUM(cnum)));
  2505.     if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
  2506.       }
  2507.       return(-1);
  2508.     }
  2509.  
  2510.   if (ChDir(pcon->connectpath) != 0)
  2511.     {
  2512.       DEBUG(0,("Can't change directory to %s\n",pcon->connectpath));
  2513.       pcon->open = False;
  2514.       unbecome_user();
  2515.       if (!IS_IPC(cnum)) {
  2516.     yield_connection(cnum,
  2517.              lp_servicename(SNUM(cnum)),
  2518.              lp_max_connections(SNUM(cnum)));
  2519.     if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
  2520.       }
  2521.       return(-5);      
  2522.     }
  2523.  
  2524.   string_set(&pcon->origpath,pcon->connectpath);
  2525.  
  2526. #if SOFTLINK_OPTIMISATION
  2527.   /* resolve any soft links early */
  2528.   {
  2529.     pstring s;
  2530.     strcpy(s,pcon->connectpath);
  2531.     GetWd(s);
  2532.     string_set(&pcon->connectpath,s);
  2533.     ChDir(pcon->connectpath);
  2534.   }
  2535. #endif
  2536.  
  2537.   num_connections_open++;
  2538.   add_session_user(user);
  2539.   
  2540.   /* execute any "preexec = " line */
  2541.   if (*lp_preexec(SNUM(cnum)))
  2542.     {
  2543.       pstring cmd;
  2544.       strcpy(cmd,lp_preexec(SNUM(cnum)));
  2545.       standard_sub(cnum,cmd);
  2546.       smbrun(cmd,NULL);
  2547.     }
  2548.   
  2549.   /* we've finished with the sensitive stuff */
  2550.   unbecome_user();
  2551.  
  2552.   {
  2553.     extern struct from_host Client_info;
  2554.     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
  2555.                 timestring(),
  2556.                 Client_info.name,Client_info.addr,
  2557.                 lp_servicename(SNUM(cnum)),user,
  2558.                 pcon->uid,
  2559.                 pcon->gid,
  2560.                 (int)getpid()));
  2561.   }
  2562.  
  2563.   return(cnum);
  2564. }
  2565.  
  2566.  
  2567. /****************************************************************************
  2568.   find first available file slot
  2569. ****************************************************************************/
  2570. int find_free_file(void )
  2571. {
  2572.   int i;
  2573.   for (i=1;i<MAX_OPEN_FILES;i++)
  2574.     if (!Files[i].open)
  2575.       return(i);
  2576.   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
  2577.   return(-1);
  2578. }
  2579.  
  2580. /****************************************************************************
  2581.   find first available connection slot, starting from a random position.
  2582. The randomisation stops problems with the server dieing and clients
  2583. thinking the server is still available.
  2584. ****************************************************************************/
  2585. static int find_free_connection(int hash )
  2586. {
  2587.   int i;
  2588.   BOOL used=False;
  2589.   hash = (hash % (MAX_CONNECTIONS-2))+1;
  2590.  
  2591.  again:
  2592.  
  2593.   for (i=hash+1;i!=hash;)
  2594.     {
  2595.       if (!Connections[i].open && Connections[i].used == used) 
  2596.     {
  2597.       DEBUG(3,("found free connection number %d\n",i));
  2598.       return(i);
  2599.     }
  2600.       i++;
  2601.       if (i == MAX_CONNECTIONS)
  2602.     i = 1;
  2603.     }
  2604.  
  2605.   if (!used)
  2606.     {
  2607.       used = !used;
  2608.       goto again;
  2609.     }
  2610.  
  2611.   DEBUG(1,("ERROR! Out of connection structures\n"));
  2612.   return(-1);
  2613. }
  2614.  
  2615.  
  2616. /****************************************************************************
  2617. reply for the core protocol
  2618. ****************************************************************************/
  2619. int reply_corep(char *outbuf)
  2620. {
  2621.   int outsize = set_message(outbuf,1,0,True);
  2622.  
  2623.   Protocol = PROTOCOL_CORE;
  2624.  
  2625.   return outsize;
  2626. }
  2627.  
  2628.  
  2629. /****************************************************************************
  2630. reply for the coreplus protocol
  2631. ****************************************************************************/
  2632. int reply_coreplus(char *outbuf)
  2633. {
  2634.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2635.   int outsize = set_message(outbuf,13,0,True);
  2636.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  2637.                  readbraw and writebraw (possibly) */
  2638.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2639.   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
  2640.  
  2641.   Protocol = PROTOCOL_COREPLUS;
  2642.  
  2643.   return outsize;
  2644. }
  2645.  
  2646.  
  2647. /****************************************************************************
  2648. reply for the lanman 1.0 protocol
  2649. ****************************************************************************/
  2650. int reply_lanman1(char *outbuf)
  2651. {
  2652.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2653.   int secword=0;
  2654.   BOOL doencrypt = SMBENCRYPT();
  2655.   time_t t = time(NULL);
  2656.  
  2657.   if (lp_security()>=SEC_USER) secword |= 1;
  2658.   if (doencrypt) secword |= 2;
  2659.  
  2660.   set_message(outbuf,13,doencrypt?8:0,True);
  2661.   SSVAL(outbuf,smb_vwv1,secword); 
  2662. #ifdef SMB_PASSWD
  2663.   /* Create a token value and add it to the outgoing packet. */
  2664.   if (doencrypt) 
  2665.     generate_next_challenge(smb_buf(outbuf));
  2666. #endif
  2667.  
  2668.   Protocol = PROTOCOL_LANMAN1;
  2669.  
  2670.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2671.     DEBUG(3,("using password server validation\n"));
  2672. #ifdef SMB_PASSWD
  2673.   if (doencrypt) set_challenge(smb_buf(outbuf));    
  2674. #endif
  2675.   }
  2676.  
  2677.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2678.   SSVAL(outbuf,smb_vwv2,maxxmit);
  2679.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
  2680.   SSVAL(outbuf,smb_vwv4,1);
  2681.   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
  2682.                  readbraw writebraw (possibly) */
  2683.   SIVAL(outbuf,smb_vwv6,getpid());
  2684.   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
  2685.  
  2686.   put_dos_date(outbuf,smb_vwv8,t);
  2687.  
  2688.   return (smb_len(outbuf)+4);
  2689. }
  2690.  
  2691.  
  2692. /****************************************************************************
  2693. reply for the lanman 2.0 protocol
  2694. ****************************************************************************/
  2695. int reply_lanman2(char *outbuf)
  2696. {
  2697.   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  2698.   int secword=0;
  2699.   BOOL doencrypt = SMBENCRYPT();
  2700.   time_t t = time(NULL);
  2701.  
  2702.   if (lp_security()>=SEC_USER) secword |= 1;
  2703.   if (doencrypt) secword |= 2;
  2704.  
  2705.   set_message(outbuf,13,doencrypt?8:0,True);
  2706.   SSVAL(outbuf,smb_vwv1,secword); 
  2707. #ifdef SMB_PASSWD
  2708.   /* Create a token value and add it to the outgoing packet. */
  2709.   if (doencrypt) 
  2710.     generate_next_challenge(smb_buf(outbuf));
  2711. #endif
  2712.  
  2713.   SIVAL(outbuf,smb_vwv6,getpid());
  2714.  
  2715.   Protocol = PROTOCOL_LANMAN2;
  2716.  
  2717.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2718.     DEBUG(3,("using password server validation\n"));
  2719. #ifdef SMB_PASSWD
  2720.     if (doencrypt) set_challenge(smb_buf(outbuf));    
  2721. #endif
  2722.   }
  2723.  
  2724.   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  2725.   SSVAL(outbuf,smb_vwv2,maxxmit);
  2726.   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
  2727.   SSVAL(outbuf,smb_vwv4,1);
  2728.   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
  2729.   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
  2730.   put_dos_date(outbuf,smb_vwv8,t);
  2731.  
  2732.   return (smb_len(outbuf)+4);
  2733. }
  2734.  
  2735. /****************************************************************************
  2736. reply for the nt protocol
  2737. ****************************************************************************/
  2738. int reply_nt1(char *outbuf)
  2739. {
  2740.   int capabilities=0x300; /* has dual names + lock_and_read */
  2741.   int secword=0;
  2742.   BOOL doencrypt = SMBENCRYPT();
  2743.  
  2744.   if (lp_security()>=SEC_USER) secword |= 1;
  2745.   if (doencrypt) secword |= 2;
  2746.  
  2747.   set_message(outbuf,17,doencrypt?8:0,True);
  2748.   CVAL(outbuf,smb_vwv1) = secword;
  2749. #ifdef SMB_PASSWD
  2750.   /* Create a token value and add it to the outgoing packet. */
  2751.   if (doencrypt) {
  2752.     generate_next_challenge(smb_buf(outbuf));
  2753.     /* Tell the nt machine how long the challenge is. */
  2754.     SSVALS(outbuf,smb_vwv16+1,8);
  2755.   }
  2756. #endif
  2757.  
  2758.   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
  2759.  
  2760.   Protocol = PROTOCOL_NT1;
  2761.  
  2762.   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  2763.     DEBUG(3,("using password server validation\n"));
  2764. #ifdef SMB_PASSWD
  2765.     if (doencrypt) set_challenge(smb_buf(outbuf));    
  2766. #endif
  2767.   }
  2768.  
  2769.   if (lp_readraw() && lp_writeraw())
  2770.     capabilities |= 1;
  2771.  
  2772.   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
  2773.   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
  2774.   SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
  2775.   SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
  2776.   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
  2777.   put_long_date(outbuf+smb_vwv11+1,time(NULL));
  2778.   SSVALS(outbuf,smb_vwv15+1,TimeDiff(time(NULL))/60);
  2779.  
  2780.   return (smb_len(outbuf)+4);
  2781. }
  2782.  
  2783.  
  2784. /* these are the protocol lists used for auto architecture detection:
  2785.  
  2786. WinNT 3.51:
  2787. protocol [PC NETWORK PROGRAM 1.0]
  2788. protocol [XENIX CORE]
  2789. protocol [MICROSOFT NETWORKS 1.03]
  2790. protocol [LANMAN1.0]
  2791. protocol [Windows for Workgroups 3.1a]
  2792. protocol [LM1.2X002]
  2793. protocol [LANMAN2.1]
  2794. protocol [NT LM 0.12]
  2795.  
  2796. Win95:
  2797. protocol [PC NETWORK PROGRAM 1.0]
  2798. protocol [XENIX CORE]
  2799. protocol [MICROSOFT NETWORKS 1.03]
  2800. protocol [LANMAN1.0]
  2801. protocol [Windows for Workgroups 3.1a]
  2802. protocol [LM1.2X002]
  2803. protocol [LANMAN2.1]
  2804. protocol [NT LM 0.12]
  2805.  
  2806. OS/2:
  2807. protocol [PC NETWORK PROGRAM 1.0]
  2808. protocol [XENIX CORE]
  2809. protocol [LANMAN1.0]
  2810. protocol [LM1.2X002]
  2811. protocol [LANMAN2.1]
  2812. */
  2813.  
  2814. /*
  2815.   * Modified to recognize the architecture of the remote machine better.
  2816.   *
  2817.   * This appears to be the matrix of which protocol is used by which
  2818.   * MS product.
  2819.        Protocol                       WfWg    Win95   WinNT  OS/2
  2820.        PC NETWORK PROGRAM 1.0          1       1       1      1
  2821.        XENIX CORE                                      2      2
  2822.        MICROSOFT NETWORKS 3.0          2       2       
  2823.        DOS LM1.2X002                   3       3       
  2824.        MICROSOFT NETWORKS 1.03                         3
  2825.        DOS LANMAN2.1                   4       4       
  2826.        LANMAN1.0                                       4      3
  2827.        Windows for Workgroups 3.1a     5       5       5
  2828.        LM1.2X002                                       6      4
  2829.        LANMAN2.1                                       7      5
  2830.        NT LM 0.12                              6       8
  2831.   *
  2832.   *  tim@fsg.com 09/29/95
  2833.   */
  2834.   
  2835. #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
  2836. #define ARCH_WIN95    0x2
  2837. #define    ARCH_OS2      0xC      /* Again OS/2 is like NT */
  2838. #define ARCH_WINNT    0x8
  2839. #define ARCH_SAMBA    0x10
  2840.  
  2841. #define ARCH_ALL      0x1F
  2842.  
  2843. /* List of supported protocols, most desired first */
  2844. struct {
  2845.   char *proto_name;
  2846.   char *short_name;
  2847.   int (*proto_reply_fn)(char *);
  2848.   int protocol_level;
  2849. } supported_protocols[] = {
  2850.   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
  2851.   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
  2852.   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  2853.   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  2854.   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
  2855.   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
  2856.   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
  2857.   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
  2858.   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
  2859.   {NULL,NULL},
  2860. };
  2861.  
  2862.  
  2863. /****************************************************************************
  2864.   reply to a negprot
  2865. ****************************************************************************/
  2866. static int reply_negprot(char *inbuf,char *outbuf)
  2867. {
  2868.   extern fstring remote_arch;
  2869.   int outsize = set_message(outbuf,1,0,True);
  2870.   int Index=0;
  2871.   int choice= -1;
  2872.   int protocol;
  2873.   char *p;
  2874.   int bcc = SVAL(smb_buf(inbuf),-2);
  2875.   int arch = ARCH_ALL;
  2876.  
  2877.   p = smb_buf(inbuf)+1;
  2878.   while (p < (smb_buf(inbuf) + bcc))
  2879.     { 
  2880.       Index++;
  2881.       DEBUG(3,("Requested protocol [%s]\n",p));
  2882.       if (strcsequal(p,"Windows for Workgroups 3.1a"))
  2883.     arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
  2884.       else if (strcsequal(p,"DOS LM1.2X002"))
  2885.     arch &= ( ARCH_WFWG | ARCH_WIN95 );
  2886.       else if (strcsequal(p,"DOS LANMAN2.1"))
  2887.     arch &= ( ARCH_WFWG | ARCH_WIN95 );
  2888.       else if (strcsequal(p,"NT LM 0.12"))
  2889.     arch &= ( ARCH_WIN95 | ARCH_WINNT );
  2890.       else if (strcsequal(p,"LANMAN2.1"))
  2891.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  2892.       else if (strcsequal(p,"LM1.2X002"))
  2893.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  2894.       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
  2895.     arch &= ARCH_WINNT;
  2896.       else if (strcsequal(p,"XENIX CORE"))
  2897.     arch &= ( ARCH_WINNT | ARCH_OS2 );
  2898.       else if (strcsequal(p,"Samba")) {
  2899.     arch = ARCH_SAMBA;
  2900.     break;
  2901.       }
  2902.  
  2903.       p += strlen(p) + 2;
  2904.     }
  2905.     
  2906.   switch ( arch ) {
  2907.   case ARCH_SAMBA:
  2908.     strcpy(remote_arch,"Samba");
  2909.     break;
  2910.   case ARCH_WFWG:
  2911.     strcpy(remote_arch,"WfWg");
  2912.     break;
  2913.   case ARCH_WIN95:
  2914.     strcpy(remote_arch,"Win95");
  2915.     break;
  2916.   case ARCH_WINNT:
  2917.     strcpy(remote_arch,"WinNT");
  2918.     break;
  2919.   case ARCH_OS2:
  2920.     strcpy(remote_arch,"OS2");
  2921.     break;
  2922.   default:
  2923.     strcpy(remote_arch,"UNKNOWN");
  2924.     break;
  2925.   }
  2926.  
  2927.   /* possibly reload - change of architecture */
  2928.   reload_services(True);      
  2929.     
  2930.   /* a special case to stop password server loops */
  2931.   if (Index == 1 && strequal(remote_machine,myhostname) && 
  2932.       lp_security()==SEC_SERVER)
  2933.     exit_server("Password server loop!");
  2934.   
  2935.   /* Check for protocols, most desirable first */
  2936.   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
  2937.     {
  2938.       p = smb_buf(inbuf)+1;
  2939.       Index = 0;
  2940.       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
  2941.     while (p < (smb_buf(inbuf) + bcc))
  2942.       { 
  2943.         if (strequal(p,supported_protocols[protocol].proto_name))
  2944.           choice = Index;
  2945.         Index++;
  2946.         p += strlen(p) + 2;
  2947.       }
  2948.       if(choice != -1)
  2949.     break;
  2950.     }
  2951.   
  2952.   SSVAL(outbuf,smb_vwv0,choice);
  2953.   if(choice != -1) {
  2954.     extern fstring remote_proto;
  2955.     strcpy(remote_proto,supported_protocols[protocol].short_name);
  2956.     reload_services(True);          
  2957.     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
  2958.     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
  2959.   }
  2960.   else {
  2961.     DEBUG(0,("No protocol supported !\n"));
  2962.   }
  2963.   SSVAL(outbuf,smb_vwv0,choice);
  2964.   
  2965.   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
  2966.  
  2967.   return(outsize);
  2968. }
  2969.  
  2970.  
  2971. /****************************************************************************
  2972.   parse a connect packet
  2973. ****************************************************************************/
  2974. void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
  2975. {
  2976.   char *p = smb_buf(buf) + 1;
  2977.   char *p2;
  2978.  
  2979.   DEBUG(4,("parsing connect string %s\n",p));
  2980.     
  2981.   p2 = strrchr(p,'\\');
  2982.   if (p2 == NULL)
  2983.     strcpy(service,p);
  2984.   else
  2985.     strcpy(service,p2+1);
  2986.   
  2987.   p += strlen(p) + 2;
  2988.   
  2989.   strcpy(password,p);
  2990.   *pwlen = strlen(password);
  2991.  
  2992.   p += strlen(p) + 2;
  2993.  
  2994.   strcpy(dev,p);
  2995.   
  2996.   *user = 0;
  2997.   p = strchr(service,'%');
  2998.   if (p != NULL)
  2999.     {
  3000.       *p = 0;
  3001.       strcpy(user,p+1);
  3002.     }
  3003. }
  3004.  
  3005.  
  3006. /****************************************************************************
  3007. close all open files for a connection
  3008. ****************************************************************************/
  3009. static void close_open_files(int cnum)
  3010. {
  3011.   int i;
  3012.   for (i=0;i<MAX_OPEN_FILES;i++)
  3013.     if( Files[i].cnum == cnum && Files[i].open) {
  3014.       close_file(i);
  3015.     }
  3016. }
  3017.  
  3018.  
  3019.  
  3020. /****************************************************************************
  3021. close a cnum
  3022. ****************************************************************************/
  3023. void close_cnum(int cnum, int uid)
  3024. {
  3025.   extern struct from_host Client_info;
  3026.  
  3027.   DirCacheFlush(SNUM(cnum));
  3028.  
  3029.   unbecome_user();
  3030.  
  3031.   if (!OPEN_CNUM(cnum))
  3032.     {
  3033.       DEBUG(0,("Can't close cnum %d\n",cnum));
  3034.       return;
  3035.     }
  3036.  
  3037.   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
  3038.               timestring(),
  3039.               Client_info.name,Client_info.addr,
  3040.               lp_servicename(SNUM(cnum))));
  3041.  
  3042.   yield_connection(cnum,
  3043.            lp_servicename(SNUM(cnum)),
  3044.            lp_max_connections(SNUM(cnum)));
  3045.  
  3046.   if (lp_status(SNUM(cnum)))
  3047.     yield_connection(cnum,"STATUS.",MAXSTATUS);
  3048.  
  3049.   close_open_files(cnum);
  3050.   dptr_closecnum(cnum);
  3051.  
  3052.   /* execute any "postexec = " line */
  3053.   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
  3054.     {
  3055.       pstring cmd;
  3056.       strcpy(cmd,lp_postexec(SNUM(cnum)));
  3057.       standard_sub(cnum,cmd);
  3058.       smbrun(cmd,NULL);
  3059.       unbecome_user();
  3060.     }
  3061.  
  3062.   unbecome_user();
  3063.   /* execute any "root postexec = " line */
  3064.   if (*lp_rootpostexec(SNUM(cnum)))
  3065.     {
  3066.       pstring cmd;
  3067.       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
  3068.       standard_sub(cnum,cmd);
  3069.       smbrun(cmd,NULL);
  3070.     }
  3071.  
  3072.   Connections[cnum].open = False;
  3073.   num_connections_open--;
  3074.   if (Connections[cnum].ngroups && Connections[cnum].groups)
  3075.     {
  3076.       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
  3077.     free(Connections[cnum].groups);
  3078.       free(Connections[cnum].igroups);
  3079.       Connections[cnum].groups = NULL;
  3080.       Connections[cnum].igroups = NULL;
  3081.       Connections[cnum].ngroups = 0;
  3082.     }
  3083.  
  3084.   string_set(&Connections[cnum].user,"");
  3085.   string_set(&Connections[cnum].dirpath,"");
  3086.   string_set(&Connections[cnum].connectpath,"");
  3087. }
  3088.  
  3089.  
  3090. /****************************************************************************
  3091. simple routines to do connection counting
  3092. ****************************************************************************/
  3093. BOOL yield_connection(int cnum,char *name,int max_connections)
  3094. {
  3095.   struct connect_record crec;
  3096.   pstring fname;
  3097.   FILE *f;
  3098.   int mypid = getpid();
  3099.   int i;
  3100.  
  3101.   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
  3102.  
  3103.   if (max_connections <= 0)
  3104.     return(True);
  3105.  
  3106.   bzero(&crec,sizeof(crec));
  3107.  
  3108.   strcpy(fname,lp_lockdir());
  3109.   standard_sub(cnum,fname);
  3110.   trim_string(fname,"","/");
  3111.  
  3112.   strcat(fname,"/");
  3113.   strcat(fname,name);
  3114.   strcat(fname,".LCK");
  3115.  
  3116.   f = fopen(fname,"r+");
  3117.   if (!f)
  3118.     {
  3119.       DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
  3120.       return(False);
  3121.     }
  3122.  
  3123.   fseek(f,0,SEEK_SET);
  3124.  
  3125.   /* find a free spot */
  3126.   for (i=0;i<max_connections;i++)
  3127.     {
  3128.       if (fread(&crec,sizeof(crec),1,f) != 1)
  3129.     {
  3130.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  3131.       fclose(f);
  3132.       return(False);
  3133.     }
  3134.       if (crec.pid == mypid && crec.cnum == cnum)
  3135.     break;
  3136.     }
  3137.  
  3138.   if (crec.pid != mypid || crec.cnum != cnum)
  3139.     {
  3140.       fclose(f);
  3141.       DEBUG(2,("Entry not found in lock file %s\n",fname));
  3142.       return(False);
  3143.     }
  3144.  
  3145.   bzero((void *)&crec,sizeof(crec));
  3146.   
  3147.   /* remove our mark */
  3148.   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
  3149.       fwrite(&crec,sizeof(crec),1,f) != 1)
  3150.     {
  3151.       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
  3152.       fclose(f);
  3153.       return(False);
  3154.     }
  3155.  
  3156.   DEBUG(3,("Yield successful\n"));
  3157.  
  3158.   fclose(f);
  3159.   return(True);
  3160. }
  3161.  
  3162.  
  3163. /****************************************************************************
  3164. simple routines to do connection counting
  3165. ****************************************************************************/
  3166. BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
  3167. {
  3168.   struct connect_record crec;
  3169.   pstring fname;
  3170.   FILE *f;
  3171.   int snum = SNUM(cnum);
  3172.   int i,foundi= -1;
  3173.   int total_recs;
  3174.  
  3175.   if (max_connections <= 0)
  3176.     return(True);
  3177.  
  3178.   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
  3179.  
  3180.   strcpy(fname,lp_lockdir());
  3181.   standard_sub(cnum,fname);
  3182.   trim_string(fname,"","/");
  3183.  
  3184.   if (!directory_exist(fname,NULL))
  3185.     mkdir(fname,0755);
  3186.  
  3187.   strcat(fname,"/");
  3188.   strcat(fname,name);
  3189.   strcat(fname,".LCK");
  3190.  
  3191.   if (!file_exist(fname,NULL))
  3192.     {
  3193.       f = fopen(fname,"w");
  3194.       if (f) fclose(f);
  3195.     }
  3196.  
  3197.   total_recs = file_size(fname) / sizeof(crec);
  3198.  
  3199.   f = fopen(fname,"r+");
  3200.  
  3201.   if (!f)
  3202.     {
  3203.       DEBUG(1,("couldn't open lock file %s\n",fname));
  3204.       return(False);
  3205.     }
  3206.  
  3207.   /* find a free spot */
  3208.   for (i=0;i<max_connections;i++)
  3209.     {
  3210.  
  3211.       if (i>=total_recs || 
  3212.       fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
  3213.       fread(&crec,sizeof(crec),1,f) != 1)
  3214.     {
  3215.       if (foundi < 0) foundi = i;
  3216.       break;
  3217.     }
  3218.  
  3219.       if (Clear && crec.pid && !process_exists(crec.pid))
  3220.     {
  3221.       fseek(f,i*sizeof(crec),SEEK_SET);
  3222.       bzero((void *)&crec,sizeof(crec));
  3223.       fwrite(&crec,sizeof(crec),1,f);
  3224.       if (foundi < 0) foundi = i;
  3225.       continue;
  3226.     }
  3227.       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
  3228.     {
  3229.       foundi=i;
  3230.       if (!Clear) break;
  3231.     }
  3232.     }  
  3233.  
  3234.   if (foundi < 0)
  3235.     {
  3236.       DEBUG(3,("no free locks in %s\n",fname));
  3237.       fclose(f);
  3238.       return(False);
  3239.     }      
  3240.  
  3241.   /* fill in the crec */
  3242.   bzero((void *)&crec,sizeof(crec));
  3243.   crec.magic = 0x280267;
  3244.   crec.pid = getpid();
  3245.   crec.cnum = cnum;
  3246.   crec.uid = Connections[cnum].uid;
  3247.   crec.gid = Connections[cnum].gid;
  3248.   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
  3249.   crec.start = time(NULL);
  3250.  
  3251.   {
  3252.     extern struct from_host Client_info;
  3253.     StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
  3254.     StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
  3255.   }
  3256.   
  3257.   /* make our mark */
  3258.   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
  3259.       fwrite(&crec,sizeof(crec),1,f) != 1)
  3260.     {
  3261.       fclose(f);
  3262.       return(False);
  3263.     }
  3264.  
  3265.   fclose(f);
  3266.   return(True);
  3267. }
  3268.  
  3269. #if DUMP_CORE
  3270. /*******************************************************************
  3271. prepare to dump a core file - carefully!
  3272. ********************************************************************/
  3273. static BOOL dump_core(void)
  3274. {
  3275.   char *p;
  3276.   pstring dname;
  3277.   strcpy(dname,debugf);
  3278.   if ((p=strrchr(dname,'/'))) *p=0;
  3279.   strcat(dname,"/corefiles");
  3280.   mkdir(dname,0700);
  3281.   sys_chown(dname,getuid(),getgid());
  3282.   chmod(dname,0700);
  3283.   if (chdir(dname)) return(False);
  3284.   umask(~(0700));
  3285.  
  3286. #ifndef NO_GETRLIMIT
  3287. #ifdef RLIMIT_CORE
  3288.   {
  3289.     struct rlimit rlp;
  3290.     getrlimit(RLIMIT_CORE, &rlp);
  3291.     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
  3292.     setrlimit(RLIMIT_CORE, &rlp);
  3293.     getrlimit(RLIMIT_CORE, &rlp);
  3294.     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
  3295.   }
  3296. #endif
  3297. #endif
  3298.  
  3299.  
  3300.   DEBUG(0,("Dumping core in %s\n",dname));
  3301.   return(True);
  3302. }
  3303. #endif
  3304.  
  3305. /****************************************************************************
  3306. exit the server
  3307. ****************************************************************************/
  3308. void exit_server(char *reason)
  3309. {
  3310.   static int firsttime=1;
  3311.   int i;
  3312.  
  3313.   if (!firsttime) exit(0);
  3314.   firsttime = 0;
  3315.  
  3316.   unbecome_user();
  3317.   DEBUG(2,("Closing connections\n"));
  3318.   for (i=0;i<MAX_CONNECTIONS;i++)
  3319.     if (Connections[i].open)
  3320.       close_cnum(i,-1);
  3321. #ifdef DFS_AUTH
  3322.   if (dcelogin_atmost_once)
  3323.     dfs_unlogin();
  3324. #endif
  3325.   if (!reason) {   
  3326.     int oldlevel = DEBUGLEVEL;
  3327.     DEBUGLEVEL = 10;
  3328.     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
  3329.     if (last_inbuf)
  3330.       show_msg(last_inbuf);
  3331.     DEBUGLEVEL = oldlevel;
  3332.     DEBUG(0,("===============================================================\n"));
  3333. #if DUMP_CORE
  3334.     if (dump_core()) return;
  3335. #endif
  3336.   }    
  3337.   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
  3338.   exit(0);
  3339. }
  3340.  
  3341. /****************************************************************************
  3342. do some standard substitutions in a string
  3343. ****************************************************************************/
  3344. void standard_sub(int cnum,char *s)
  3345. {
  3346.   if (!strchr(s,'%')) return;
  3347.  
  3348.   if (VALID_CNUM(cnum))
  3349.     {
  3350.       string_sub(s,"%S",lp_servicename(Connections[cnum].service));
  3351.       string_sub(s,"%P",Connections[cnum].connectpath);
  3352.       string_sub(s,"%u",Connections[cnum].user);
  3353.       if (strstr(s,"%H")) {
  3354.     char *home = get_home_dir(Connections[cnum].user);
  3355.     if (home) string_sub(s,"%H",home);
  3356.       }
  3357.     }
  3358.   standard_sub_basic(s);
  3359. }
  3360.  
  3361. /*
  3362. These flags determine some of the permissions required to do an operation 
  3363.  
  3364. Note that I don't set NEED_WRITE on some write operations because they
  3365. are used by some brain-dead clients when printing, and I don't want to
  3366. force write permissions on print services.
  3367. */
  3368. #define AS_USER (1<<0)
  3369. #define NEED_WRITE (1<<1)
  3370. #define TIME_INIT (1<<2)
  3371. #define CAN_IPC (1<<3)
  3372. #define AS_GUEST (1<<5)
  3373.  
  3374.  
  3375. /* 
  3376.    define a list of possible SMB messages and their corresponding
  3377.    functions. Any message that has a NULL function is unimplemented -
  3378.    please feel free to contribute implementations!
  3379. */
  3380. struct smb_message_struct
  3381. {
  3382.   int code;
  3383.   char *name;
  3384.   int (*fn)();
  3385.   int flags;
  3386. #if PROFILING
  3387.   unsigned long time;
  3388. #endif
  3389. }
  3390.  smb_messages[] = {
  3391.  
  3392.     /* CORE PROTOCOL */
  3393.  
  3394.    {SMBnegprot,"SMBnegprot",reply_negprot,0},
  3395.    {SMBtcon,"SMBtcon",reply_tcon,0},
  3396.    {SMBtdis,"SMBtdis",reply_tdis,0},
  3397.    {SMBexit,"SMBexit",reply_exit,0},
  3398.    {SMBioctl,"SMBioctl",reply_ioctl,0},
  3399.    {SMBecho,"SMBecho",reply_echo,0},
  3400.    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
  3401.    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
  3402.    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, 
  3403.    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
  3404.    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
  3405.    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
  3406.    {SMBsearch,"SMBsearch",reply_search,AS_USER},
  3407.    {SMBopen,"SMBopen",reply_open,AS_USER},
  3408.  
  3409.    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
  3410.    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
  3411.    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
  3412.  
  3413.    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
  3414.    {SMBread,"SMBread",reply_read,AS_USER},
  3415.    {SMBwrite,"SMBwrite",reply_write,AS_USER},
  3416.    {SMBclose,"SMBclose",reply_close,AS_USER},
  3417.    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
  3418.    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
  3419.    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
  3420.    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
  3421.  
  3422.    /* this is a Pathworks specific call, allowing the 
  3423.       changing of the root path */
  3424.    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
  3425.  
  3426.    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
  3427.    {SMBflush,"SMBflush",reply_flush,AS_USER},
  3428.    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
  3429.    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
  3430.    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
  3431.    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
  3432.    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
  3433.    {SMBlock,"SMBlock",reply_lock,AS_USER},
  3434.    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
  3435.    
  3436.    /* CORE+ PROTOCOL FOLLOWS */
  3437.    
  3438.    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
  3439.    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
  3440.    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
  3441.    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
  3442.    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
  3443.    
  3444.    /* LANMAN1.0 PROTOCOL FOLLOWS */
  3445.    
  3446.    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
  3447.    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
  3448.    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
  3449.    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
  3450.    {SMBwritec,"SMBwritec",NULL,AS_USER},
  3451.    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
  3452.    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
  3453.    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
  3454.    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
  3455.    {SMBioctls,"SMBioctls",NULL,AS_USER},
  3456.    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
  3457.    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
  3458.    
  3459.    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
  3460.    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
  3461.    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
  3462.    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
  3463.    
  3464.    {SMBffirst,"SMBffirst",reply_search,AS_USER},
  3465.    {SMBfunique,"SMBfunique",reply_search,AS_USER},
  3466.    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
  3467.  
  3468.    /* LANMAN2.0 PROTOCOL FOLLOWS */
  3469.    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
  3470.    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
  3471.    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
  3472.    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
  3473.  
  3474.    /* messaging routines */
  3475.    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
  3476.    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
  3477.    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
  3478.    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
  3479.  
  3480.    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
  3481.    
  3482.    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
  3483.    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
  3484.    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
  3485.    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
  3486.  };
  3487.  
  3488. /****************************************************************************
  3489. return a string containing the function name of a SMB command
  3490. ****************************************************************************/
  3491. char *smb_fn_name(int type)
  3492. {
  3493.   static char *unknown_name = "SMBunknown";
  3494.   static int num_smb_messages = 
  3495.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  3496.   int match;
  3497.  
  3498.   for (match=0;match<num_smb_messages;match++)
  3499.     if (smb_messages[match].code == type)
  3500.       break;
  3501.  
  3502.   if (match == num_smb_messages)
  3503.     return(unknown_name);
  3504.  
  3505.   return(smb_messages[match].name);
  3506. }
  3507.  
  3508.  
  3509. /****************************************************************************
  3510. do a switch on the message type, and return the response size
  3511. ****************************************************************************/
  3512. static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
  3513. {
  3514.   static int pid= -1;
  3515.   int outsize = 0;
  3516.   static int num_smb_messages = 
  3517.     sizeof(smb_messages) / sizeof(struct smb_message_struct);
  3518.   int match;
  3519.  
  3520. #if PROFILING
  3521.   struct timeval msg_start_time;
  3522.   struct timeval msg_end_time;
  3523.   static unsigned long total_time = 0;
  3524.  
  3525.   GetTimeOfDay(&msg_start_time);
  3526. #endif
  3527.  
  3528.   if (pid == -1)
  3529.     pid = getpid();
  3530.  
  3531.   errno = 0;
  3532.   last_message = type;
  3533.  
  3534.   /* make sure this is an SMB packet */
  3535.   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
  3536.     {
  3537.       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
  3538.       return(-1);
  3539.     }
  3540.  
  3541.   for (match=0;match<num_smb_messages;match++)
  3542.     if (smb_messages[match].code == type)
  3543.       break;
  3544.  
  3545.   if (match == num_smb_messages)
  3546.     {
  3547.       DEBUG(0,("Unknown message type %d!\n",type));
  3548.       outsize = reply_unknown(inbuf,outbuf);
  3549.     }
  3550.   else
  3551.     {
  3552.       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
  3553.       if (smb_messages[match].fn)
  3554.     {
  3555.       int cnum = SVAL(inbuf,smb_tid);
  3556.       int flags = smb_messages[match].flags;
  3557.       int uid = SVAL(inbuf,smb_uid);
  3558.  
  3559.       /* does this protocol need to be run as root? */
  3560.       if (!(flags & AS_USER))
  3561.         unbecome_user();
  3562.  
  3563.       /* does this protocol need to be run as the connected user? */
  3564.       if ((flags & AS_USER) && !become_user(cnum,uid))
  3565.         return(ERROR(ERRSRV,ERRinvnid));
  3566.  
  3567.       /* does it need write permission? */
  3568.       if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
  3569.         return(ERROR(ERRSRV,ERRaccess));
  3570.  
  3571.       /* ipc services are limited */
  3572.       if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
  3573.         return(ERROR(ERRSRV,ERRaccess));        
  3574.  
  3575.       /* load service specific parameters */
  3576.       if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
  3577.         return(ERROR(ERRSRV,ERRaccess));
  3578.  
  3579.       /* does this protocol need to be run as guest? */
  3580.       if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
  3581.         return(ERROR(ERRSRV,ERRaccess));
  3582.  
  3583.       last_inbuf = inbuf;
  3584.  
  3585.       outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
  3586.     }
  3587.       else
  3588.     {
  3589.       outsize = reply_unknown(inbuf,outbuf);
  3590.     }
  3591.     }
  3592.  
  3593. #if PROFILING
  3594.   GetTimeOfDay(&msg_end_time);
  3595.   if (!(smb_messages[match].flags & TIME_INIT))
  3596.     {
  3597.       smb_messages[match].time = 0;
  3598.       smb_messages[match].flags |= TIME_INIT;
  3599.     }
  3600.   {
  3601.     unsigned long this_time =     
  3602.       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
  3603.     (msg_end_time.tv_usec - msg_start_time.tv_usec);
  3604.     smb_messages[match].time += this_time;
  3605.     total_time += this_time;
  3606.   }
  3607.   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
  3608.        smb_fn_name(type),smb_messages[match].time,
  3609.     (100.0*smb_messages[match].time) / total_time));
  3610. #endif
  3611.  
  3612.   return(outsize);
  3613. }
  3614.  
  3615.  
  3616. /****************************************************************************
  3617. construct a chained reply and add it to the already made reply
  3618.  
  3619. inbuf points to the original message start.
  3620. inbuf2 points to the smb_wct part of the secondary message
  3621. type is the type of the secondary message
  3622. outbuf points to the original outbuffer
  3623. outbuf2 points to the smb_wct field of the new outbuffer
  3624. size is the total length of the incoming message (from inbuf1)
  3625. bufsize is the total buffer size
  3626.  
  3627. return how many bytes were added to the response
  3628. ****************************************************************************/
  3629. int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
  3630. {
  3631.   int outsize = 0;
  3632.   char *ibuf,*obuf;
  3633.   static BOOL in_chain = False;
  3634.   static char *last_outbuf=NULL;
  3635.   BOOL was_inchain = in_chain;
  3636.   int insize_remaining;
  3637.   static int insize_deleted;
  3638.  
  3639.  
  3640.   chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
  3641.   if (was_inchain)
  3642.     outbuf = last_outbuf;
  3643.   else
  3644.     insize_deleted = 0;
  3645.  
  3646.  
  3647.   insize_deleted = 0;
  3648.   inbuf2 -= insize_deleted;
  3649.   insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
  3650.   insize_deleted += size - (insize_remaining + smb_wct);
  3651.  
  3652.   in_chain = True;
  3653.   last_outbuf = outbuf;
  3654.  
  3655.  
  3656.   /* allocate some space for the in and out buffers of the chained message */
  3657.   ibuf = (char *)malloc(size + SAFETY_MARGIN);
  3658.   obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
  3659.  
  3660.   if (!ibuf || !obuf)
  3661.     {
  3662.       DEBUG(0,("Out of memory in chain reply\n"));
  3663.       return(ERROR(ERRSRV,ERRnoresource));
  3664.     }
  3665.  
  3666.   ibuf += SMB_ALIGNMENT;
  3667.   obuf += SMB_ALIGNMENT;
  3668.  
  3669.   /* create the in buffer */
  3670.   memcpy(ibuf,inbuf,smb_wct);
  3671.   memcpy(ibuf+smb_wct,inbuf2,insize_remaining);
  3672.   CVAL(ibuf,smb_com) = type;
  3673.  
  3674.   /* create the out buffer */
  3675.   bzero(obuf,smb_size);
  3676.  
  3677.   set_message(obuf,0,0,True);
  3678.   CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
  3679.   
  3680.   memcpy(obuf+4,ibuf+4,4);
  3681.   CVAL(obuf,smb_rcls) = SUCCESS;
  3682.   CVAL(obuf,smb_reh) = 0;
  3683.   CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set 
  3684.                                  means a reply */
  3685.   SSVAL(obuf,smb_flg2,1); /* say we support long filenames */
  3686.   SSVAL(obuf,smb_err,SUCCESS);
  3687.   SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
  3688.   SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
  3689.   SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
  3690.   SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
  3691.  
  3692.   DEBUG(3,("Chained message\n"));
  3693.   show_msg(ibuf);
  3694.  
  3695.   /* process the request */
  3696.   outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
  3697.                bufsize-chain_size);
  3698.  
  3699.   /* copy the new reply header over the old one, but preserve 
  3700.      the smb_com field */
  3701.   memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
  3702.  
  3703.   /* and copy the data from the reply to the right spot */
  3704.   memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
  3705.  
  3706.   /* free the allocated buffers */
  3707.   if (ibuf) free(ibuf-SMB_ALIGNMENT);
  3708.   if (obuf) free(obuf-SMB_ALIGNMENT);
  3709.  
  3710.   in_chain = was_inchain;
  3711.  
  3712.   /* return how much extra has been added to the packet */
  3713.   return(outsize - smb_wct);
  3714. }
  3715.  
  3716.  
  3717.  
  3718. /****************************************************************************
  3719.   construct a reply to the incoming packet
  3720. ****************************************************************************/
  3721. int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
  3722. {
  3723.   int type = CVAL(inbuf,smb_com);
  3724.   int outsize = 0;
  3725.   int msg_type = CVAL(inbuf,0);
  3726.  
  3727.   smb_last_time = time(NULL);
  3728.  
  3729.   chain_size = 0;
  3730.  
  3731.   bzero(outbuf,smb_size);
  3732.  
  3733.   if (msg_type != 0)
  3734.     return(reply_special(inbuf,outbuf));  
  3735.  
  3736.   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
  3737.   set_message(outbuf,0,0,True);
  3738.   
  3739.   memcpy(outbuf+4,inbuf+4,4);
  3740.   CVAL(outbuf,smb_rcls) = SUCCESS;
  3741.   CVAL(outbuf,smb_reh) = 0;
  3742.   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
  3743.                                  means a reply */
  3744.   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
  3745.   SSVAL(outbuf,smb_err,SUCCESS);
  3746.   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
  3747.   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
  3748.   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
  3749.   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
  3750.  
  3751.   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
  3752.  
  3753.   if(outsize > 4)
  3754.     smb_setlen(outbuf,outsize - 4);
  3755.   return(outsize);
  3756. }
  3757.  
  3758.  
  3759. /****************************************************************************
  3760.   process commands from the client
  3761. ****************************************************************************/
  3762. void process(void )
  3763. {
  3764.   static int trans_num = 0;
  3765.   int nread;
  3766.   extern struct from_host Client_info;
  3767.   extern int Client;
  3768.  
  3769.   fromhost(Client,&Client_info);
  3770.   
  3771.   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3772.   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
  3773.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  3774.     return;
  3775.  
  3776.   InBuffer += SMB_ALIGNMENT;
  3777.   OutBuffer += SMB_ALIGNMENT;
  3778.  
  3779. #if PRIME_NMBD
  3780.   DEBUG(3,("priming nmbd\n"));
  3781.   {
  3782.     struct in_addr ip;
  3783.     ip = *interpret_addr2("localhost");
  3784.     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
  3785.     *OutBuffer = 0;
  3786.     send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM);
  3787.   }
  3788. #endif    
  3789.  
  3790.   last_user.cnum = -1;
  3791.   
  3792.   while (True)
  3793.     {
  3794.       int32 len;      
  3795.       int msg_type;
  3796.       int msg_flags;
  3797.       int type;
  3798.       int deadtime = lp_deadtime()*60;
  3799.       int counter;
  3800.       int last_keepalive=0;
  3801.  
  3802.       if (deadtime <= 0)
  3803.     deadtime = DEFAULT_SMBD_TIMEOUT;
  3804.  
  3805.       if (lp_readprediction())
  3806.     do_read_prediction();
  3807.  
  3808.       {
  3809.     extern pstring share_del_pending;
  3810.     if (*share_del_pending) {
  3811.       unbecome_user();
  3812.       if (!unlink(share_del_pending))
  3813.         DEBUG(3,("Share file deleted %s\n",share_del_pending));
  3814.       else
  3815.         DEBUG(2,("Share del failed of %s\n",share_del_pending));
  3816.       share_del_pending[0] = 0;
  3817.     }
  3818.       }
  3819.  
  3820.       if (share_mode_pending) {
  3821.     unbecome_user();
  3822.     check_share_modes();
  3823.     share_mode_pending=False;
  3824.       }
  3825.  
  3826.       errno = 0;      
  3827.  
  3828.       for (counter=SMBD_SELECT_LOOP; 
  3829.        !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
  3830.        counter += SMBD_SELECT_LOOP)
  3831.     {
  3832.       int i;
  3833.       time_t t;
  3834.       BOOL allidle = True;
  3835.       extern int keepalive;
  3836.  
  3837.       /* check for socket failure */
  3838.       if (errno == EBADF) {
  3839.         DEBUG(3,("%s Bad file descriptor - exiting\n",timestring()));
  3840.         return;
  3841.       }
  3842.  
  3843.       t = time(NULL);
  3844.  
  3845.       /* become root again if waiting */
  3846.       unbecome_user();
  3847.  
  3848.       /* check for smb.conf reload */
  3849.       if (!(counter%SMBD_RELOAD_CHECK))
  3850.         reload_services(True);
  3851.  
  3852.       /* check the share modes every 10 secs */
  3853.       if (!(counter%SHARE_MODES_CHECK))
  3854.         check_share_modes();
  3855.  
  3856.       /* clean the share modes every 5 minutes */
  3857.       if (!(counter%SHARE_MODES_CLEAN))
  3858.         clean_share_files();
  3859.  
  3860.       /* automatic timeout if all connections are closed */      
  3861.       if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
  3862.         DEBUG(2,("%s Closing idle connection\n",timestring()));
  3863.         return;
  3864.       }
  3865.  
  3866.       if (keepalive && (counter-last_keepalive)>keepalive) {
  3867.         if (!send_keepalive(Client)) {
  3868.           DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
  3869.           return;
  3870.         }
  3871.         last_keepalive = counter;
  3872.       }
  3873.  
  3874.       /* check for connection timeouts */
  3875.       for (i=0;i<MAX_CONNECTIONS;i++)
  3876.         if (Connections[i].open)
  3877.           {
  3878.         /* close dirptrs on connections that are idle */
  3879.         if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
  3880.           dptr_idlecnum(i);
  3881.  
  3882.         if (Connections[i].num_files_open > 0 ||
  3883.             (t-Connections[i].lastused)<deadtime)
  3884.           allidle = False;
  3885.           }
  3886.  
  3887.       if (allidle && num_connections_open>0) {
  3888.         DEBUG(2,("%s Closing idle connection 2\n",timestring()));
  3889.         return;
  3890.       }
  3891.     }
  3892.  
  3893.       msg_type = CVAL(InBuffer,0);
  3894.       msg_flags = CVAL(InBuffer,1);
  3895.       type = CVAL(InBuffer,smb_com);
  3896.  
  3897.       len = smb_len(InBuffer);
  3898.  
  3899.       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
  3900.  
  3901.       nread = len + 4;
  3902.       
  3903.       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
  3904.  
  3905. #ifdef WITH_VTP
  3906.       if(trans_num == 1 && VT_Check(InBuffer)) {
  3907.         VT_Process();
  3908.         return;
  3909.       }
  3910. #endif
  3911.  
  3912.  
  3913.       if (msg_type == 0)
  3914.     show_msg(InBuffer);
  3915.  
  3916.       nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
  3917.       
  3918.       if(nread > 0) {
  3919.         if (CVAL(OutBuffer,0) == 0)
  3920.       show_msg(OutBuffer);
  3921.     
  3922.         if (nread != smb_len(OutBuffer) + 4) 
  3923.       {
  3924.         DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
  3925.              nread,
  3926.              smb_len(OutBuffer)));
  3927.       }
  3928.     else
  3929.       send_smb(Client,OutBuffer);
  3930.       }
  3931.       trans_num++;
  3932.     }
  3933. }
  3934.  
  3935.  
  3936. /****************************************************************************
  3937.   initialise connect, service and file structs
  3938. ****************************************************************************/
  3939. static void init_structs(void )
  3940. {
  3941.   int i;
  3942.   get_myname(myhostname,&myip);
  3943.  
  3944.   for (i=0;i<MAX_CONNECTIONS;i++)
  3945.     {
  3946.       Connections[i].open = False;
  3947.       Connections[i].num_files_open=0;
  3948.       Connections[i].lastused=0;
  3949.       Connections[i].used=False;
  3950.       string_init(&Connections[i].user,"");
  3951.       string_init(&Connections[i].dirpath,"");
  3952.       string_init(&Connections[i].connectpath,"");
  3953.       string_init(&Connections[i].origpath,"");
  3954.     }
  3955.  
  3956.   for (i=0;i<MAX_OPEN_FILES;i++)
  3957.     {
  3958.       Files[i].open = False;
  3959.       string_init(&Files[i].name,"");
  3960.     }
  3961.  
  3962.   init_dptrs();
  3963. }
  3964.  
  3965. /****************************************************************************
  3966. usage on the program
  3967. ****************************************************************************/
  3968. void usage(char *pname)
  3969. {
  3970.   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
  3971.  
  3972.   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
  3973.   printf("Version %s\n",VERSION);
  3974.   printf("\t-D                    become a daemon\n");
  3975.   printf("\t-p port               listen on the specified port\n");
  3976.   printf("\t-d debuglevel         set the debuglevel\n");
  3977.   printf("\t-l log basename.      Basename for log/debug files\n");
  3978.   printf("\t-s services file.     Filename of services file\n");
  3979.   printf("\t-P                    passive only\n");
  3980.   printf("\t-a                    overwrite log file, don't append\n");
  3981.   printf("\n");
  3982. }
  3983.  
  3984.  
  3985. /****************************************************************************
  3986.   main program
  3987. ****************************************************************************/
  3988. int main(int argc,char *argv[])
  3989. {
  3990.   extern BOOL append_log;
  3991.   /* shall I run as a daemon */
  3992.   BOOL is_daemon = False;
  3993.   int port = 139;
  3994.   int opt;
  3995.   extern char *optarg;
  3996.  
  3997. #ifdef SecureWare
  3998.   set_auth_parameters(argc,argv);
  3999.   setluid(0);
  4000. #endif
  4001.  
  4002. #ifdef OSF1_ENH_SEC
  4003.   set_auth_parameters(argc,argv);
  4004. #endif
  4005.  
  4006.   append_log = True;
  4007.  
  4008.   TimeInit();
  4009.  
  4010.   strcpy(debugf,SMBLOGFILE);  
  4011.  
  4012.   setup_logging(argv[0],False);
  4013.  
  4014.   charset_initialise();
  4015.  
  4016.   /* make absolutely sure we run as root - to handle cases whre people
  4017.      are crazy enough to have it setuid */
  4018. #ifdef USE_SETRES
  4019.   setresuid(0,0,0);
  4020. #else
  4021.   setuid(0);
  4022.   seteuid(0);
  4023.   setuid(0);
  4024.   seteuid(0);
  4025. #endif
  4026.  
  4027.   fault_setup(exit_server);
  4028.  
  4029.   umask(0777 & ~DEF_CREATE_MASK);
  4030.  
  4031.   initial_uid = geteuid();
  4032.   initial_gid = getegid();
  4033.  
  4034.   if (initial_gid != 0 && initial_uid == 0)
  4035.     {
  4036. #ifdef HPUX
  4037.       setresgid(0,0,0);
  4038. #else
  4039.       setgid(0);
  4040.       setegid(0);
  4041. #endif
  4042.     }
  4043.  
  4044.   initial_uid = geteuid();
  4045.   initial_gid = getegid();
  4046.  
  4047.  
  4048.   /* this is for people who can't start the program correctly */
  4049.   while (argc > 1 && (*argv[1] != '-'))
  4050.     {
  4051.       argv++;
  4052.       argc--;
  4053.     }
  4054.  
  4055.   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
  4056.     switch (opt)
  4057.       {
  4058.       case 'O':
  4059.     strcpy(user_socket_options,optarg);
  4060.     break;
  4061.       case 'i':
  4062.     strcpy(scope,optarg);
  4063.     break;
  4064.       case 'P':
  4065.     {
  4066.       extern BOOL passive;
  4067.       passive = True;
  4068.     }
  4069.     break;    
  4070.       case 's':
  4071.     strcpy(servicesf,optarg);
  4072.     break;
  4073.       case 'l':
  4074.     strcpy(debugf,optarg);
  4075.     break;
  4076.       case 'a':
  4077.     {
  4078.       extern BOOL append_log;
  4079.       append_log = !append_log;
  4080.     }
  4081.     break;
  4082.       case 'D':
  4083.     is_daemon = True;
  4084.     break;
  4085.       case 'd':
  4086.     if (*optarg == 'A')
  4087.       DEBUGLEVEL = 10000;
  4088.     else
  4089.       DEBUGLEVEL = atoi(optarg);
  4090.     break;
  4091.       case 'p':
  4092.     port = atoi(optarg);
  4093.     break;
  4094.       case 'h':
  4095.     usage(argv[0]);
  4096.     exit(0);
  4097.     break;
  4098.       default:
  4099.     usage(argv[0]);
  4100.     exit(1);
  4101.       }
  4102.  
  4103.   reopen_logs();
  4104.  
  4105.   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
  4106.   DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
  4107.  
  4108.   GetWd(OriginalDir);
  4109.  
  4110. #ifndef NO_GETRLIMIT
  4111. #ifdef RLIMIT_NOFILE
  4112.   {
  4113.     struct rlimit rlp;
  4114.     getrlimit(RLIMIT_NOFILE, &rlp);
  4115.     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
  4116.     setrlimit(RLIMIT_NOFILE, &rlp);
  4117.     getrlimit(RLIMIT_NOFILE, &rlp);
  4118.     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
  4119.   }
  4120. #endif
  4121. #endif
  4122.  
  4123.   
  4124.   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
  4125.     getuid(),getgid(),geteuid(),getegid()));
  4126.  
  4127.   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
  4128.     {
  4129.       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
  4130.       exit(1);
  4131.     }
  4132.  
  4133.   init_structs();
  4134.  
  4135.   if (!reload_services(False))
  4136.     return(-1);    
  4137.  
  4138. #ifndef NO_SIGNAL_TEST
  4139.   signal(SIGHUP,SIGNAL_CAST sig_hup);
  4140. #endif
  4141.   
  4142.   DEBUG(3,("%s loaded services\n",timestring()));
  4143.  
  4144.   if (!is_daemon && !is_a_socket(0))
  4145.     {
  4146.       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
  4147.       is_daemon = True;
  4148.     }
  4149.  
  4150.   if (is_daemon)
  4151.     {
  4152.       DEBUG(3,("%s becoming a daemon\n",timestring()));
  4153.       become_daemon();
  4154.     }
  4155.  
  4156.   if (open_sockets(is_daemon,port))
  4157.     {      
  4158.       /* possibly reload the services file. */
  4159.       reload_services(True);
  4160.  
  4161.       maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
  4162.  
  4163.       if (*lp_rootdir())
  4164.     {
  4165.       if (sys_chroot(lp_rootdir()) == 0)
  4166.         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
  4167.     }
  4168.  
  4169.       process();
  4170.       close_sockets();
  4171.     }
  4172.   exit_server("normal exit");
  4173.   return(0);
  4174. }
  4175.  
  4176.  
  4177.